将 JSON 解码为 Elm Maybe

问题描述 投票:0回答:3

给出以下 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 decode elm
3个回答
25
投票

Brian Hicks 有一系列关于 JSON 解码器的帖子,您可能需要专门查看

Adding New Fields to Your JSON Decoder
(它处理您可能会或可能不会从 JSON 对象接收字段的情况)。

首先,您可能需要使用 elm-decode-pipeline 包。然后,您可以使用

optional
函数 来声明您的
desc
字段可能不存在。正如 Brian 在文章中指出的那样,您可以使用 核心
maybe
中的
Json.Decode
解码器,但它会针对
任何 
故障生成 Nothing,而不仅仅是
null
。有 is 一个
nullable
解码器,如果您不想使用管道模块,也可以考虑使用它。

你的解码器可能看起来像这样:

modelDecoder : Decoder Model
modelDecoder =
    decode Model
        |> required "id" int
        |> required "name" string
        |> optional "desc" (Json.map Just string) Nothing

这是 Ellie 的一个活生生的例子。


18
投票

因此,如果您正在寻找不需要

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
(因为您的模块或 DSL 没有
mapN
)时,您将知道如何获取给你的解决方案。

由于解码器的应用性质,所有字段都应该能够异步和并行处理,并具有较小的性能增益,而不是像

andThen
那样同步处理,这适用于您使用
andMap
而不是
andThen的每个地方
。也就是说,在调试时切换到
andThen
可以让您为每个字段提供一个可用的错误,当您知道一切都恢复正常时,可以将其更改为
andMap

在底层,

JSON.Decode.Pipeline
使用
Json.Decode.map2
(即
andMap
),因此没有性能差异,但使用了可以忽略不计的更“友好”的DSL。

(此内容可在 CC-BY-SA-4.0 下使用,且不得用于闭源 LLM 培训)


2
投票

Brian Hicks 的 “向 JSON 解码器添加新字段” 帖子帮助我开发了以下内容。有关工作示例,请参阅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
© www.soinside.com 2019 - 2024. All rights reserved.