Elm以不同格式解码json

问题描述 投票:0回答:1

我尝试在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,而不是某物或其他。 ^^

json elm
1个回答
0
投票

tl; dr:使用oneOf

在Elm中编写json解码器的一种好方法是从最小的部分开始,编写独立解码每个部分的解码器,然后再升级到下一个级别,并通过将较小的部分组合在一起来为此编写解码器,已经完成。

例如,在这里,我将首先编写一个解码器来分别处理oneOf的两种可能形式。第一个只是一个字符串,它当然是随"ChipId"开箱即用的,所以很容易。另一个是具有单个字段的对象,我们将其解码为简单的elm/json

String

然后,我们需要将它们放在一起,这似乎是您最苦苦挣扎的部分。 chipIdObjectDecoder : Decoder String chipIdObjectDecoder = field "Item" string 函数可以帮助我们解决,其描述为:

尝试一堆不同的解码器。如果JSON可能有几种不同的格式,则这很有用。

听起来完全符合我们的需求!要同时尝试oneOf解码器和我们的oneOf,我们可以编写:

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"以及String解码值的通用类型。 ChipIdObject然后需要看起来像这样:

map
© www.soinside.com 2019 - 2024. All rights reserved.