如何将 JSON 解码为由数据构造函数构建的记录?
How to decode JSON to record built by a data constructor?
有型
type User
= Anonymous
| Named {name : String, email : String}
Json.Decode.object2
不适合这里因为它的第一个参数类型是 (a -> b -> c)
但 Named
有 { email : String, name : String } -> User
类型。
如何解码给用户?
由于您的 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" }])
另一种方法是定义一个接受姓名和电子邮件的函数以及 returns 您的 Named
构造函数:
userDecoder : Decoder User
userDecoder =
let
named =
object2
(\n e -> Named { name = n, email = e })
("name" := string)
("email" := string)
in
oneOf [ null Anonymous, named ]
有型
type User
= Anonymous
| Named {name : String, email : String}
Json.Decode.object2
不适合这里因为它的第一个参数类型是 (a -> b -> c)
但 Named
有 { email : String, name : String } -> User
类型。
如何解码给用户?
由于您的 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" }])
另一种方法是定义一个接受姓名和电子邮件的函数以及 returns 您的 Named
构造函数:
userDecoder : Decoder User
userDecoder =
let
named =
object2
(\n e -> Named { name = n, email = e })
("name" := string)
("email" := string)
in
oneOf [ null Anonymous, named ]