我尝试在榆木中解码一些json。
我正在接收的对象可能具有两种不同的形状。
第一种情况:
{
...
"ChipId": "NotSet"
...
}
Run Code Online (Sandbox Code Playgroud)
第二种情况:
{
...
"ChipId": {
"Item": "0000000000"
},
...
}
Run Code Online (Sandbox Code Playgroud)
因此,第一个对象很容易解码,field "ChipId" string但是如果它是复杂对象,它将失败。我已经尝试过了,Decode.andThen但无法解决。
谢谢您的帮助!
我尝试的方法是使用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
Run Code Online (Sandbox Code Playgroud)
我想这里的问题是Maybe期望什么,null而不是期望什么。^^
tl; dr:使用oneOf
在Elm中编写json解码器的一个好方法是从最小的部分开始,编写独立解码每个部分的解码器,然后再升级到下一个级别,并通过将您已经较小的部分放在一起编写一个解码器制作。
例如,在这里,我将从编写解码器开始以分别处理两种可能的形式"ChipId"。第一个只是一个字符串,它当然是带有的开箱即用的elm/json,所以很容易。另一个是具有单个字段的对象,我们将其解码为一个简单的对象String:
chipIdObjectDecoder : Decoder String
chipIdObjectDecoder =
field "Item" string
Run Code Online (Sandbox Code Playgroud)
然后,我们需要将它们放在一起,这似乎是您最苦苦挣扎的部分。这里的oneOf功能是我们的急救,其描述为:
尝试一堆不同的解码器。如果JSON可能有几种不同的格式,这将很有用。
听起来正是我们所需要的!要尝试string解码器和我们的解码器,chipIdObjectDecoder我们可以编写:
eitherStringOrChipIdObject : Decoder String
eitherStringOrChipIdObject =
oneOf [ string, chipIdObjectDecoder ]
Run Code Online (Sandbox Code Playgroud)
最后,我们需要解码"ChipId"字段本身:
field "ChipId" eitherStringOrChipIdObject
Run Code Online (Sandbox Code Playgroud)
所有这些都放在一个函数中:
chipIdDecoder : Decoder String
chipIdDecoder =
let
chipIdObjectDecoder : Decoder String
chipIdObjectDecoder =
field "Item" string
eitherStringOrChipIdObject : Decoder String
eitherStringOrChipIdObject =
oneOf [ string, chipIdObjectDecoder ]
in
field "ChipId" eitherStringOrChipIdObject
Run Code Online (Sandbox Code Playgroud)
或者稍微简化一下,因为上述内容很冗长:
chipIdDecoder : Decoder String
chipIdDecoder =
let
chipIdObjectDecoder =
field "Item" string
in
field "ChipId" (oneOf [ string, chipIdObjectDecoder ])
Run Code Online (Sandbox Code Playgroud)
最后一点,由于不清楚您的代码是否过度简化。如果"ChipId"无法将对象简化为简单的字符串,则必须使用可以同时容纳a String和a 的通用类型ChipIdObject,并将map解码后的值转换为该通用类型。eitherStringOrChipIdObject然后可能是这样的:
type alias ChipIdObject = { ... }
type ChipId
= ChipIdString String
| ChipIdObject ChipIdObject
eitherStringOrChipIdObject : Decoder ChipId
eitherStringOrChipIdObject =
oneOf
[ string |> map ChipIdString
, chipIdObjectDecoder |> map ChipIdObject
]
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
59 次 |
| 最近记录: |