将一个JSON元组解码为Elm元组

6

我的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,“更多的东西”]读作一个而不是元组的JSON格式。
如何将我的JSON解析成List(Int,String)


1
你的JSON与描述不符 - [1,"things"]是一个JSON 数组而不是JSON 对象(因为你提到了JSON元组,所以我期望它是一个JSON对象)。尝试使用{1,"things"},或者更改你的Elm解码器以接受列表的列表。 - Frank Schmitt
3个回答

20

被接受的答案比必要的要复杂。尝试:

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

8
您需要一个解码器,将大小为两个的javascript数组转换为大小为两个的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

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

运行得非常好。当元组被表示为列表时,为什么没有默认实现呢? - ptkato
2
以前有用本地JavaScript实现的“tupleN”解码器,但是它们已经被删除,建议使用index进行处理。我不确定具体的原因是什么。 - Chad Gilbert

2

我无法使用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的解决方案链接和一些问题背景会帮助人们更快地回答你的问题。希望这有所帮助。;) - user1775718
好的。Chad的解决方案是被接受的,而Simon的解决方案也在这个帖子中提到了。我的帖子是我能够让它工作的解决方案 - 所以它更像是对Chad被接受的解决方案的一种替代,而不是一个问题。我的问题与原始发布者相同。 - René Paw Christensen
抱歉,伙计。这是SO界面的糟糕设计。当它说要审查帖子时,它将你的帖子显示为问题,而不是答案!我以为你所提到的人和问题在Elm社区中是众所周知的,并且你从那里扩展了!老实说,这太荒谬了!请忽略我上面的评论。真是让人摇头! - user1775718
你正在将一个对象声明为元组。该问题使用了两个元素的数组。 - Simon H
我的代码假设JSON数据是[val1,val2],而你的数据似乎是{field1:val1,field2:val2} - Simon H

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接