将 JSON 解码为 Elm Maybe
Decode JSON into Elm Maybe
给出以下 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
}
Brian Hicks 有一系列关于 JSON 解码器的文章,您可能想专门查看 Adding New Fields to Your JSON Decoder
(它处理您可能会或可能不会从 JSON对象)。
首先,您可能想要使用 elm-decode-pipeline package. You can then use the optional
function to declare that your desc
field may not be there. As Brian points out in the article, you can use the maybe
decoder from the core Json.Decode
package, but it will produce Nothing
for any failure, not just being null
. There is a nullable
解码器,如果您不想使用管道模块,也可以考虑使用它。
您的解码器可能看起来像这样:
modelDecoder : Decoder Model
modelDecoder =
decode Model
|> required "id" int
|> required "name" string
|> optional "desc" (Json.map Just string) Nothing
布赖恩·希克斯的 "Adding New Fields to Your JSON Decoder" post helped me develop the following. For a working example, see Ellie
import 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.Decode.Pipeline
.
的 zero-dependency 解决方案
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 库才能获得这些功能。了解应用仿函数的工作原理将帮助您进一步了解,因此我建议您阅读它们。解码管道解决方案抽象了这个简单的概念,但是当您 运行 需要 Result.andMap
或任何其他 andMap
时,因为您的模块没有 mapN
或DSL,你就会知道如何找到你的解决方案。
由于解码器的应用特性,所有字段都应该能够异步和并行处理,性能增益很小,而不是像 andThen
那样同步处理,这适用于您使用的每个地方andMap
超过 andThen
。也就是说,当调试切换到 andThen
时,您可以为每个字段提供一个可用错误,当您知道一切正常时,可以将其更改为 andMap
。
在幕后,JSON.Decode.Pipeline
使用 Json.Decode.map2
(即 andMap
),因此没有性能差异,但使用的 DSL 可忽略不计 "friendly"。
给出以下 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
}
Brian Hicks 有一系列关于 JSON 解码器的文章,您可能想专门查看 Adding New Fields to Your JSON Decoder
(它处理您可能会或可能不会从 JSON对象)。
首先,您可能想要使用 elm-decode-pipeline package. You can then use the optional
function to declare that your desc
field may not be there. As Brian points out in the article, you can use the maybe
decoder from the core Json.Decode
package, but it will produce Nothing
for any failure, not just being null
. There is a nullable
解码器,如果您不想使用管道模块,也可以考虑使用它。
您的解码器可能看起来像这样:
modelDecoder : Decoder Model
modelDecoder =
decode Model
|> required "id" int
|> required "name" string
|> optional "desc" (Json.map Just string) Nothing
布赖恩·希克斯的 "Adding New Fields to Your JSON Decoder" post helped me develop the following. For a working example, see Ellie
import 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.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 库才能获得这些功能。了解应用仿函数的工作原理将帮助您进一步了解,因此我建议您阅读它们。解码管道解决方案抽象了这个简单的概念,但是当您 运行 需要 Result.andMap
或任何其他 andMap
时,因为您的模块没有 mapN
或DSL,你就会知道如何找到你的解决方案。
由于解码器的应用特性,所有字段都应该能够异步和并行处理,性能增益很小,而不是像 andThen
那样同步处理,这适用于您使用的每个地方andMap
超过 andThen
。也就是说,当调试切换到 andThen
时,您可以为每个字段提供一个可用错误,当您知道一切正常时,可以将其更改为 andMap
。
在幕后,JSON.Decode.Pipeline
使用 Json.Decode.map2
(即 andMap
),因此没有性能差异,但使用的 DSL 可忽略不计 "friendly"。