2016-11-20 70 views
1

我發現將舊的Model狀態遷移到新的Model狀態非常困難。如何編寫一個JSON解碼器,將類型ModelV1轉換爲類型ModelV2

假設我們的代碼最初有Model,並且我們堅持它到本地存儲。

現在我們要爲我們的模型添加一個額外的字段「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.oneOf嘗試解析器和使用Json.Decode.succeed提供一個默認的備用。如果你想代表沒有createdAt0,你可以寫你的解碼器是這樣的:

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-c​​onverts-from-type-modelv1 -to-type-modelv2#comment68636044_40703098 – Jigar