json - Elm以不同格式解码json
问题描述
我尝试在 elm 中解码一些 json。
我收到的物品可能有两种不同的形状。
第一种情况:
{
...
"ChipId": "NotSet"
...
}
第二种情况:
{
...
"ChipId": {
"Item": "0000000000"
},
...
}
所以第一个可以很容易地解码,field "ChipId" string
但如果它是复杂的对象,它就会失败。我已经尝试过了,Decode.andThen
但我无法解决它。
谢谢您的帮助!
更新 1 - 解码器失败
我尝试的方法是使用Maybe
.
chipIdDecoder : Decoder String
chipIdDecoder =
let
chipIdIdDecoder : Decoder String
chipIdIdDecoder =
field "ChipId" (field "Fields" (firstElementDecoder string))
chooseChipId : Maybe String -> Decoder String
chooseChipId c =
case c of
Just id ->
case id of
"ChipId" ->
chipIdIdDecoder
_ ->
succeed ""
Nothing ->
fail "Chip Id is invalid"
in
nullable (field "ChipId" string)
|> andThen chooseChipId
我想这里的问题是Maybe
期望某物或某物,null
而不是某物或其他东西。^^
解决方案
tl;博士:使用oneOf
在 Elm 中编写 json 解码器的一个好方法是从最小的部分开始,编写独立解码每个部分的解码器,然后向上移动到下一个级别,并通过将您已经完成的较小部分组合在一起来编写一个解码器制成。
例如,在这里,我将首先编写一个解码器来分别处理两种可能的形式"ChipId"
。第一个只是一个字符串,它当然是开箱即用的elm/json
,所以这很容易。另一个是具有单个字段的对象,我们将其解码为简单的String
:
chipIdObjectDecoder : Decoder String
chipIdObjectDecoder =
field "Item" string
然后我们需要把它们放在一起,这似乎是你最挣扎的部分。这里的oneOf
函数来救我们,它的描述说:
尝试一堆不同的解码器。如果 JSON 可能有几种不同的格式,这将很有用。
听起来正是我们需要的!要尝试string
解码器和我们的,chipIdObjectDecoder
我们可以编写:
eitherStringOrChipIdObject : Decoder String
eitherStringOrChipIdObject =
oneOf [ string, chipIdObjectDecoder ]
最后我们需要对"ChipId"
字段本身进行解码:
field "ChipId" eitherStringOrChipIdObject
所有这些都放在一个函数中:
chipIdDecoder : Decoder String
chipIdDecoder =
let
chipIdObjectDecoder : Decoder String
chipIdObjectDecoder =
field "Item" string
eitherStringOrChipIdObject : Decoder String
eitherStringOrChipIdObject =
oneOf [ string, chipIdObjectDecoder ]
in
field "ChipId" eitherStringOrChipIdObject
或者稍微简化一下,因为上面的内容相当冗长:
chipIdDecoder : Decoder String
chipIdDecoder =
let
chipIdObjectDecoder =
field "Item" string
in
field "ChipId" (oneOf [ string, chipIdObjectDecoder ])
最后一点,因为不清楚您的代码是否过于简化。如果"ChipId"
对象不能简化为简单的字符串,则必须使用可以同时保存 aString
和 a的通用类型ChipIdObject
,以及map
该通用类型的解码值。eitherStringOrChipIdObject
那么可能是这样的:
type alias ChipIdObject = { ... }
type ChipId
= ChipIdString String
| ChipIdObject ChipIdObject
eitherStringOrChipIdObject : Decoder ChipId
eitherStringOrChipIdObject =
oneOf
[ string |> map ChipIdString
, chipIdObjectDecoder |> map ChipIdObject
]
推荐阅读
- java - 有没有办法在一个 Talend Open Studio 项目中容纳多个文件而不会耗尽内存?
- java - Java - 为来自外部库的类定义一个通用接口
- python - 蟒龟 tr
- java - 使用客户端凭据授权从具有 Java HttpClient 的服务器检索访问令牌
- html - 自定义字体无法在 Wordpress 上的其他计算机上呈现
- python - 在 Visual Studio 中将目录添加到 PATH
- amazon-web-services - 在没有源文件夹名称的情况下将文件复制到 s3
- html - 将图像大小调整为父 div?仅使用父 div?
- c# - 使用 ssh.net.sftp 从 sftp 目录下载大量文件的有效方法?
- html - 未对齐的块对象