将JSON解码为Elm也许吧

时间:2017-02-17 21:46:12

标签: json decode elm

给出以下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
    }

3 个答案:

答案 0 :(得分:17)

Brian Hicks在JSON解码器上有一系列帖子,您可能希望专门查看Adding New Fields to Your JSON Decoder(它处理您可能会或可能不会从JSON对象接收字段的场景)。

首先,您可能想要使用elm-decode-pipeline package。然后,您可以使用optional function声明您的desc字段可能不存在。正如Brian在文章中指出的那样,您可以使用maybe中的the core Json.Decode package解码器,但它会为任何失败产生Nothing,而不仅仅是{{} 1}}。 一个nullable解码器,如果您不想使用管道模块,也可以考虑使用它。

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

null

Here's a live example on Ellie.

答案 1 :(得分:9)

因此,如果您正在寻找不需要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构造函数作为applicative functor(因为你需要更多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))

这两者都可以ListDecode.list modelDecoder一起使用。我希望应用函数在标准库中,但是您必须进入所有* -extra库才能获得这些功能。了解应用程序仿函数如何工作将有助于您了解更多内容,因此我建议您阅读它们。解码管道解决方案抽象了这个简单的概念,但是当您遇到Result.andMap或任何其他andMap的需求时,因为您的模块不是mapN或一个DSL,你将知道如何找到你的解决方案。

答案 2 :(得分:2)

布莱恩希克斯' "Adding New Fields to Your JSON Decoder"帖子帮助我开发了以下内容。有关工作示例,请参阅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