2016-11-20 5 views
1

이전 모델 상태를 새 모델 상태로 마이그레이션하는 것이 매우 어렵다는 것을 알고 있습니다.ModelV1 형식에서 ModelV2 형식으로 변환하는 Json 디코더를 작성하는 방법

처음에는 코드에 Model이 있고이를 localstorage에 유지한다고 가정 해 보겠습니다.

이제 모델에 하나의 추가 필드 "createdAt"를 추가하려고합니다. 따라서 새 필드 별칭을 만들었습니다.

import Json.Decode as D 
import Html as H 


type alias Todo = {id:Int, title: String} 

jsonV1 = """ 

    {"id":1, "title":"Elm-Rocks"} 

""" 

jsonV2 = """ 

    {"id":1, "title":"Elm-Rocks", "createdAt":1479633701604} 


""" 


type alias TodoV2 = {id:Int, title: String, createdAt:Int} 

decode = D.map2 Todo 
    (D.field "id" D.int) 
    (D.field "title" D.string) 

decodeV2 = D.map3 TodoV2 
    (D.field "id" D.int) 
    (D.field "title" D.string) 
    (D.field "createdAt" D.int) 


result1 = D.decodeString decode jsonV1 

result2 = D.decodeString decodeV2 jsonV2 


type alias Model = {todos: List Todo} 
type alias ModelV2 = {todos: List TodoV2} 


main = H.div[] [ 
    H.div[][H.text (toString result1)] 
    , H.div[][H.text (toString result2)] 
    ] 

어떻게 V1/V2 형식 JSON 문자열 중 하나를 받아들이는 디코더/함수를 작성하고 나에게 ModelV2 기록을 제공합니다.

나는 Decoder.andThen의 알고하지만 난 당신이 새 필드는 선택 할 경우, 당신은 하나의 모델을 사용할 수 있습니다 todoDecoderV1: ??? -> TodoV2

답변

2

당신은 파서를 시도하고 Json.Decode.succeed를 사용하여 기본 대체를 제공하기 위해 Json.Decode.oneOf를 사용할 수 있습니다. 당신이 0createdAt의 부재를 표현하고 싶었다면, 당신은이처럼 디코더를 작성할 수

decode = D.map3 TodoV2 
    (D.field "id" D.int) 
    (D.field "title" D.string) 
    (D.oneOf [(D.field "createdAt" D.int), D.succeed 0]) 

그러나, 더 정확하게 현실을 표현하기 위해, 당신의 모델이 createdAt이 그래서 변경하는 것이 추천 유형을 Maybe Int으로 변경하여 선택적. 이것은 make impossible states impossible에 좋은 방법입니다.

type alias TodoV3 = {id:Int, title: String, createdAt:Maybe Int} 

decodeV3 = D.map3 TodoV3 
    (D.field "id" D.int) 
    (D.field "title" D.string) 
    (D.maybe (D.field "createdAt" D.int)) 
+0

"불가능한 상태"의 대화를 끝내고 아직 끝내지 않았습니다. 그러나 createdAt는 선택적 필드가 아니며 어쩌면 코드 전체에 체크하지 않으려합니다. 당신은 스키마가 바뀔 때마다, 아마도 사용하겠다고 제안하고 있습니까? 그게 거래에 가까울 것입니다. 새로운 코드는 유효한 생성 된 코드를 생성하도록 보장됩니다. 이 디코딩은 스키마 이전 중에 만 수행됩니다. – Jigar

+2

이해할 수 있습니다. 당신은 그 길을 가기로 결정한다면 합리적인 채무 불이행이 필요합니다. 첫 번째 oneOf 예제에서는 제로를 사용했지만 비즈니스에 필요한 모든 것을 사용할 수 있습니다. –

0

의 구현을 작성하는 방법을 모르겠어요.

type alias Todo = {id:Int, title: String, createdAt: Maybe Int} 

decode = D.map3 Todo 
    (D.field "id" D.int) 
    (D.field "title" D.string) 
    D.maybe(D.field "createdAt" D.int) 
+0

감사하지만, http://stackoverflow.com/questions/40702856/how-to-write-a-json-decoder-that-converts-from-type-modelv1 어쩌면 를 사용하여 내 반응을 확인합니까 -to-type-modelv2 # comment68636044_40703098 – Jigar