给定以下的JSON:
[
{
"id": 0,
"name": "Item 1",
"desc": "The first item"
},
{
"id": 1,
"name": "Item 2"
}
]
如何将其解码为以下模型:
type alias Model =
{ id : Int
, name : String
, desc : Maybe String
}
向JSON解码器添加新字段
(处理当你可能会或可能不会从JSON对象接收到一个字段的情况)。请注意,本文保留了HTML标签。
首先,您可能想使用elm-decode-pipeline包。然后,您可以使用optional
函数声明您的desc
字段可能不存在。正如Brian在文章中指出的那样,您可以使用核心Json.Decode
包中的maybe
解码器,但它将对任何失败产生Nothing
,而不仅仅是null
。如果您不想使用管道模块,还有一个nullable
解码器可供考虑。
你的解码器可能看起来像这样:
modelDecoder : Decoder Model
modelDecoder =
decode Model
|> required "id" int
|> required "name" string
|> optional "desc" (Json.map Just string) Nothing
所以,如果你正在寻找一种不需要依赖于Json.Decode.Pipeline
的解决方案。
import Json.Decode as Decode exposing (Decoder)
modelDecoder : Decoder Model
modelDecoder =
Decode.map3 Model
(Decode.field "id" Decode.int)
(Decode.field "name" Decode.string)
(Decode.maybe (Decode.field "desc" Decode.string))
如果你想使用Model
构造函数作为可应用函子来完成此操作(因为你需要超过8个项目)。
import Json.Decode as Decode exposing (Decoder)
import Json.Decode.Extra as Decode
modelDecoder : Decoder Model
modelDecoder =
Decode.succeed Model
|> Decode.andMap (Decode.field "id" Decode.int)
|> Decode.andMap (Decode.field "name" Decode.string)
|> Decode.andMap (Decode.maybe (Decode.field "desc" Decode.string))
这两个函数都可以与List
和Decode.list modelDecoder
一起使用。我希望这些应用函数能够成为标准库的一部分,但你需要到所有的* -extra库中去获取这些功能。了解应用函子的工作原理将有助于您更好地理解后续内容,因此建议您阅读相关资料。Decode Pipeline解决方案抽象了这个简单的概念,但当您遇到需要使用Result.andMap
或任何其他andMap
时,因为您的模块或DSL没有mapN
,您将知道如何解决问题。
由于解码器的应用性质,所有字段都应该能够异步并行处理,并且可以获得小的性能提升,而不是像andThen
一样同步处理,这适用于您在每个使用andMap
而不是andThen
的地方。话虽如此,在调试时切换到andThen
可以为您提供一个可用的错误位置,当您知道一切正常时,可以将其更改为andMap
。
在幕后,JSON.Decode.Pipeline
使用Json.Decode.map2
(即andMap
),因此没有性能差异,但使用的DSL略微更加“友好”。
andThen
路由的一个优点是您有机会绑定特定的错误消息,但这在调试时通常很有用。 andMap
在技术上应该是可并行化的,因为它是适用的。 - toastalimport Html exposing (..)
import Json.Decode as Decode exposing (Decoder)
import Json.Decode.Pipeline as JP
import String
type alias Item =
{ id : Int
, name : String
, desc : Maybe String
}
main =
Decode.decodeString (Decode.list itemDecoder) payload
|> toString
|> String.append "JSON "
|> text
itemDecoder : Decoder Item
itemDecoder =
JP.decode Item
|> JP.required "id" Decode.int
|> JP.required "name" Decode.string
|> JP.optional "desc" (Decode.map Just Decode.string) Nothing
(Json.map Just string)
而不是Json.map Just int)
。 - Matthew Rankinstring
和一个 Ellie 示例更新了它。希望能有所帮助! - bdukes