Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays elm解码非均匀阵列_Arrays_Json_Decode_Elm - Fatal编程技术网

Arrays elm解码非均匀阵列

Arrays elm解码非均匀阵列,arrays,json,decode,elm,Arrays,Json,Decode,Elm,我需要解码一个JSON数组,其中头项的类型为User,所有尾项的类型为昵称。数组长度事先未知,我无法更改JSON表示形式 JSON示例: { "userdata" : [ { "id" : 1, "name" : "MyName", "email" : "MyName@dot.com" }, { "name" : "n1" }, { "name" : "n2" } ]

我需要解码一个JSON数组,其中头项的类型为
User
,所有尾项的类型为
昵称
。数组长度事先未知,我无法更改JSON表示形式

JSON示例:

{ "userdata" : [
    {
        "id" : 1,
        "name" : "MyName",
        "email" : "MyName@dot.com"
    },
    {
        "name" : "n1"
    },
    {
        "name" : "n2"
    }
]
} 
我的类型定义:

module Decoders exposing (..)
type alias User =
    { id : Int
    , name : String
    , email : String
    }

type alias Nickname =
    { name : String
    }

type alias Model =
    { user : User
    , nicknames : List Nickname
    }
User
昵称
中还有许多其他不同的字段,但我在这里将其缩短以保持示例的简单性

解码器:

decodeUser : Json.Decode.Decoder User
decodeUser =
    Json.Decode.Pipeline.decode User
        |> Json.Decode.Pipeline.required "id" (Json.Decode.int)
        |> Json.Decode.Pipeline.required "name" (Json.Decode.string)
        |> Json.Decode.Pipeline.required "email" (Json.Decode.string)


decodeNickname : Json.Decode.Decoder Nickname
decodeNickname =
    Json.Decode.Pipeline.decode Nickname
        |> Json.Decode.Pipeline.required "name" (Json.Decode.string)


decodeModel : Json.Decode.Decoder Model
decodeModel =
    Json.Decode.Pipeline.decode Model
        |> Json.Decode.Pipeline.required "userdata" (Json.Decode.index 0 decodeUser)
        |> Json.Decode.Pipeline.hardcoded [ Nickname "Nick", Nickname "Names" ]
测试:


删除头项并将数组的其余部分反序列化为
昵称的列表的最佳方法是什么?

我将首先制作一个高阶解码器,该解码器以两个解码器作为输入:第一个解码器解码列表的头,第二个解码器解码列表的尾。签名可以是这样的:

headAndTailDecoder:Decoder a->Decoder b->Decoder(a,列表b)
下面是我实现此功能的初步尝试。这有点冗长,因为它首先将列表解码为
Json.Decode.Value
项的列表,然后在生成的列表上运行解码器:

导入Json。解码为JD(解码器)
导入结果。额外公开(合并)
头尾解码器:解码器a->解码器b->解码器(a,列表b)
头尾解码器头尾=
JD.list JD.value
|>法学博士
(\values->
实例值
[] ->
JD.fail“空列表”
h::t->
案例(JD.decodeValue head h,List.map(JD.decodeValue tail)t |>联合收割机)
(Ok headDecoded,Ok tailDecoded)->
JD.success(头解码,尾解码)
_ ->
JD.fail“无效”
)
这可能是可以优化的,但它完成了任务。根据您的输入运行会产生以下结果:

JD.field“userdata”(头和尾解码器解码用户解码昵称)
|>JD.map(\(h,t)->型号h-t)
--收益率:Ok{user={id=1,name=“MyName”,email=”MyName@dot.com},昵称=[{name=“n1”},{name=“n2”}]}

谢谢,效果很好!解码为模式匹配的
Json.decode.Value
项的好策略。
decodesModel : Test
decodesModel =
    test "Decodes a user and list of nicknames" <|
        \() ->
            let
                input =
                    """
                      { "userdata" : [
                        {
                          "id" : 1,
                          "name" : "MyName",
                          "email" : "MyName@dot.com"
                        },
                        {
                          "name" : "n1"
                        },
                        {
                          "name" : "n2"
                        }
                      ]
                      }
                    """

                decodedOutput =
                    Json.Decode.decodeString
                        Decoders.decodeModel
                        input

                nicknames =
                    [ Decoders.Nickname "n1", Decoders.Nickname "n2" ]

                user =
                    Decoders.User 1 "MyName" "MyName@dot.com"

                expectation =
                    Decoders.Model user nicknames
            in
                Expect.equal decodedOutput
                    (Ok expectation)
✗ Decodes a user and list of nicknames

Ok { user = { id = 1, name = "MyName", email = "MyName@dot.com" }, nicknames = [{ name = "n1" },{ name = "n2" }] }
╷
│ Expect.equal
╵
Ok { user = { id = 1, name = "MyName", email = "MyName@dot.com" }, nicknames = [{ name = "Nick" },{ name = "Names" }] }