【问题标题】:Decode a JSON tuple to Elm tuple将 JSON 元组解码为 Elm 元组
【发布时间】:2017-03-09 19:21:56
【问题描述】:

我的 JSON 如下所示

{ "resp":
    [ [1, "things"]
    , [2, "more things"]
    , [3, "even more things"]
    ]
}

问题是我无法将 JSON 元组解析为 Elm 元组:

decodeThings : Decoder (List (Int, String))
decodeThings = field "resp" <| list <| map2 (,) int string

它可以编译,但运行时会抛出

BadPayload "Expecting an Int at _.resp[2] but instead got [3, \"even more things\"]

由于某种原因,它仅将 [3, "even more things"] 读取为一件事,而不是 JSON 格式的元组。
如何将我的 JSON 解析为 List (Int, String)

【问题讨论】:

  • 您的 JSON 与您的描述不符 - [1, "things" ] 是 JSON array 而不是 JSON object (我希望从你提到了 JSON 元组)。请改用{1, "things" },或更改您的 Elm 解码器以接受列表列表。

标签: json elm


【解决方案1】:

接受的答案比它需要的更复杂。试试:

import Json.Decode as Decode

decodeTuple : Decode.Decoder (Int, String)
decodeTuple = 
    Decode.map2 Tuple.pair 
        (Decode.index 0 Decode.int) 
        (Decode.index 1 Decode.string)

然后,正如您所注意到的,对于列表

Decode.list decodeTuple

【讨论】:

    【解决方案2】:

    您需要一个解码器,它将大小为 2 的 javascript 数组转换为大小为 2 的 Elm 元组。这是一个示例解码器:

    arrayAsTuple2 : Decoder a -> Decoder b -> Decoder (a, b)
    arrayAsTuple2 a b =
        index 0 a
            |> andThen (\aVal -> index 1 b
            |> andThen (\bVal -> Json.Decode.succeed (aVal, bVal)))
    

    然后您可以按如下方式修改原始示例:

    decodeThings : Decoder (List (Int, String))
    decodeThings = field "resp" <| list <| arrayAsTuple2 int string
    

    (请注意,如果有两个以上的元素,我的示例解码器不会失败,但它应该让你指向正确的方向)

    【讨论】:

    • 工作就像一个魅力。当元组表示为列表时,为什么没有任何默认实现?
    • 曾经有tupleN解码器是用原生javascript实现的,但那些是removed,推荐的处理方式是使用index。我不确定到底是什么原因。
    【解决方案3】:

    我无法让 Chad Gilbert 或 Simon H 的解决方案与 Elm 0.19 一起使用。我对 Elm 很陌生,但这是我可以开始工作的:

    import Json.Decode as Decode
    import Json.Decode.Extra as Decode
    
    {-| Decodes two fields into a tuple.
    -}
    decodeAsTuple2 : String -> Decode.Decoder a -> String -> Decode.Decoder b -> Decode.Decoder (a, b)
    decodeAsTuple2 fieldA decoderA fieldB decoderB =
        let
            result : a -> b -> (a, b)
            result valueA valueB =
                (valueA, valueB)
        in
            Decode.succeed result
                |> Decode.andMap (Decode.field fieldA decoderA)
                |> Decode.andMap (Decode.field fieldB decoderB)
    

    【讨论】:

    • 嗨@Rene,我被要求审查您的问题,因为您是新来的。我要说的唯一一件事是,也许提供指向 Chad 或 Simon 的解决方案的链接以及有关您的问题的一些背景信息会帮助人们更快地为您提供答案。希望有帮助。 ;)
    • 好的。乍得的解决方案是公认的,西蒙的也在这个线程的上面。我的帖子是我可以开始工作的解决方案 - 所以它更像是乍得接受的解决方案的替代方案,然后是一个问题。我的问题和原来的海报一样。
    • 对不起,伙计。那是SO部分的糟糕UI。当它说查看帖子时,它向我展示了您的帖子,就好像这是问题,而不是答案!我认为你提到的人和问题在 Elm 社区中是众所周知的,而且你已经从那里扩展了!老实说,多么可笑!忽略我上面的评论。 smdh!
    • 您将一个对象声明为一个元组。该问题使用了两个元素的数组
    • 我的代码假设 json 数据是 [val1, val2],而您的数据似乎是 {field1: val1, field2: val2}
    猜你喜欢
    • 1970-01-01
    • 2018-07-02
    • 1970-01-01
    • 1970-01-01
    • 2017-01-12
    • 1970-01-01
    • 2021-11-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多