我的JSON看起来与此类似:
{ "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
无法根据需要获取最后两个函数进行交互。我已经通过Brian Thicks阅读了json-survival-kit的第33页,但这并没有让我走上正轨。
任何建议和讲座表示赞赏!
看起来这本书的目标是榆木0.17或以下。在榆树0.18,backtick syntax was removed。你还需要为type
使用不同的字段名称,因为它是一个保留字,所以我将它重命名为type_
。
一些注释可能有助于缩小错误。让我们注释decodeContentByType
,因为现在,分支没有返回相同的类型。三个成功的值应该是将解码器映射到预期的Content
构造函数:
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
功能。我们需要三个字段来满足Item
构造函数。第二个字段是类型,可以通过required "type" int
获得,但第三个字段依赖于"type"
值来推导出正确的构造函数。在使用Elm的andThen
解码器获取Decoder Int
值后,我们可以使用field
(使用Elm 0.18的管道语法):
decodeItem : Decoder Item
decodeItem = succeed Item
|> required "order" int
|> required "type" int
|> custom (field "type" int |> andThen decodeContentByType)