2016-11-20 76 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