如何将JSON解码为由数据构造函数构建的记录?

时间:2016-05-30 11:05:56

标签: elm

有类型

type User
  = Anonymous
  | Named {name : String, email : String}

Json.Decode.object2不适合此处,因为其第一个参数类型为(a -> b -> c),但Named具有{ email : String, name : String } -> User类型。

如何解码给用户?

2 个答案:

答案 0 :(得分:3)

另一种方法是定义一个接受名称和电子邮件并返回Named构造函数的函数:

userDecoder : Decoder User
userDecoder =
  let
    named =
      object2
        (\n e -> Named { name = n, email = e })
        ("name" := string)
        ("email" := string)
  in
    oneOf [ null Anonymous, named ]

答案 1 :(得分:2)

由于您的Named构造函数将记录作为参数,因此为名称和电子邮件记录创建类型别名可能会更加清晰。

type alias NamedUserInfo =
  { name : String
  , email : String
  }

然后,您可以重新定义User以使用别名:

type User
  = Anonymous
  | Named NamedUserInfo

虽然以上并不是绝对必要的,但我发现别名记录类型在很多方面证明是有用的。这里有用,因为它为我们提供了一个构造函数NamedUserInfo,可以让我们清楚地定义解码器:

import Json.Decode exposing (..)

namedUserInfoDecoder : Decoder NamedUserInfo
namedUserInfoDecoder =
  object2
    NamedUserInfo
    ("name" := string)
    ("email" := string)

最后,您的用户解码器可以像这样构建:

userDecoder : Decoder User
userDecoder =
  oneOf
    [ null Anonymous
    , object1 Named namedUserInfoDecoder
    ]

你可以通过这样的快速测试来运行你的例子:

exampleJson =
  """
    [{"user":null}, {"user": {"name": "John Doe", "email": "j.doe@mailg.com"}}]
  """

main =
  text <| toString <| decodeString (list ("user" := userDecoder)) exampleJson

-- Ouputs:
-- Ok ([Anonymous,Named { name = "John Doe", email = "j.doe@mailg.com" }])