2017-12-21 20 views
1

とニレへの私のJSONは、次のようになります。デコード多型JSONオブジェクトandThen

{ "items" : 
    [ { "type" : 0, "order": 10, "content": { "a" : 10, "b" : "description", ... } } 
    , { "type" : 1, "order": 11, "content": { "a" : 11, "b" : "same key, but different use", ... } } 
    , { "type" : 2, "order": 12, "content": { "c": "totally different fields", ... } } 
    ... 
    ] 
} 

と私はデコード中に作成するためにどのような労働組合のタイプを決定するtype値を使用します。そこで、elmの上記のすべてのエイリアスタイプとデコーダを定義しました。

import Json.Decode exposing (..) 
import Json.Decode.Pipeline exposing (..) 

type alias Type0Content = { a : Int, b : String } 
type alias Type1Content = { a : Int, b2 : String } 
type alias Type2Content = { c : String } 
type Content = Type0 Type0Content | Type1 Type1Content | Type2 Type2Content 
type alias Item = { order : Int, type : Int, content: Content } 

decode0 = succeed Type0Content 
    |> requiredAt ["content", "a"] int 
    |> requiredAt ["content", "b"] string 
decode1 = succeed Type1Content 
    |> requiredAt ["content", "a"] int 
    |> requiredAt ["content", "b"] string 
decode2 = succeed Type2Content 
    |> requiredAt ["content", "c"] string 
decodeContentByType hint = 
    case hint of 
     0 -> Type0 decode0 
     1 -> Type1 decode1 
     2 -> Type2 decode2 
     _ -> fail "unknown type" 
decodeItem = succeed Item 
    |> required "order" int 
    |> required "type" int `andThen` decodeContentByType 

必要に応じて最後の2つの機能を使用することはできません。 私はBrian Thicksのjson-survival-kitの33ページを読んだことがありますが、それは私を軌道に乗せませんでした。

アドバイスや講演は高く評価されました!

答えて

1

Elm 0.17以下を対象に書かれた本のようです。 Elm 0.18では、backtick syntax was removedです。また、typeのフィールド名は予約語なので別のフィールド名を使用する必要がありますので、名前をtype_に変更します。

注釈の中には、バグを絞り込むものがあります。 decodeContentByTypeに注釈を付けましょう。なぜなら、今はブランチが同じ型を返さないからです。今

decodeContentByType : Int -> Decoder Content 
decodeContentByType hint = 
    case hint of 
     0 -> map Type0 decode0 
     1 -> map Type1 decode1 
     2 -> map Type2 decode2 
     _ -> fail "unknown type" 

decodeItem機能に対処するための:3つの成功した値が予想Contentコンストラクタにデコーダをマッピングする必要があります。我々はItemコンストラクタを満たすために3つのフィールドが必要です。 2番目のフィールドはタイプで、required "type" intで取得できますが、3番目のフィールドは正しいコンストラクタを推測するために"type"の値に依存します。私たちは、エルムのfieldデコーダを使用してDecoder Int値を取得した後(エルム0.18のようにパイプラインの構文で)andThenを使用することができます。

decodeItem : Decoder Item 
decodeItem = succeed Item 
    |> required "order" int 
    |> required "type" int 
    |> custom (field "type" int |> andThen decodeContentByType) 
+1

あなたは 'required'と' custom'がJson.Decode.Pipeline' 'に属していることを言及するのを忘れてしまいました。コアパッケージに固執したい場合は、 'map3'と' field'を代わりに使うことができます。 –

+0

解決法と役立つ説明については、ChadとChrisに感謝します。非常に多くの0.18以前のチュートリアルを見つけ出し、 'Decode.Pipeline.custom'の新しい説明さえも役に立ちませんでした。あなたの記述はずっと多くを助けました。 –