2016-11-20 10 views
1

古いモデル状態を新しいモデル状態に移行することは非常に困難です。ModelV1型からModelV2型に変換するJsonデコーダを書く方法

最初にコードにModelがあり、それをlocalstorageに保存したとします。

ここで、追加のフィールド「createdAt」をモデルに追加したいので、同じタイプの新しいタイプエイリアスを作成しました。 V1/V2形式のJSON文字列のいずれかを受け入れ、私にModelV2レコードを与えること、デコーダ/関数を記述する方法

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)] 
    ] 

私はDecoder.andThenの承知していますが、私はあなたが新しいフィールドをオプションに場合は、単一のモデルを使用することができますtodoDecoderV1: ??? -> TodoV2

答えて

2

あなたはパーサを試してみて、Json.Decode.succeedを使用して、デフォルトのフォールバックを提供するために、Json.Decode.oneOfを使用することができます。しかし、

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があるように、あなたのモデルが変更されることをお勧めします:あなたは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はオプションのフィールドではないので、私は多分コード全体にチェックを入れたくありません。スキーマが変わるたびに、私はおそらく使用していることを示唆していますか?それは対処するのに大変なことです。新しいコードは、有効なcreate atを生成することを保証します。このデコードは、スキーマの移行中にのみ行われます。 – 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

関連する問題