Декодер JSON в Elm 0.18

В Elm 0.18 я хотел бы создать декодер JSON для следующих примеров:

Случай 1:

{"metadata": {"signatures":[{"metadata": {"code": "1234"}},
                            {"metadata": {"code": "5678"}}]}}  

-> { code = Just "1234" }

случай 2:

{"metadata": {"signatures":[]}} 

-> { code = Nothing }

случай 3:

{"metadata": {"signatures":[{"metadata": null}]}} 

-> { code = Nothing }

Это то, что у меня работает, но это не работает для случая 3.

type alias Code = { code : Maybe String }

let
    js = """{"metadata": {"signatures":[{"metadata": {"code": "1234"}},
                   {"metadata": {"code": "5678"}}]}}"""

    dec1 =
        Decode.at [ "metadata", "code" ] Decode.string

    dec0 =
        Decode.list dec1
            |> Decode.andThen
                (\v ->
                    if List.isEmpty v then
                        Decode.succeed Nothing
                    else
                        Decode.succeed <| List.head v
                )

    dec =
        decode Code
            |> optionalAt [ "metadata", "signatures" ] dec0 Nothing

    expected =
        Ok { code = Just "1234" }
in
    Decode.decodeString dec js
        |> Expect.equal expected

Обходным путем может быть импорт всех данных в модель, а затем получение информации из модели, но я предпочитаю избегать добавления ненужных данных в свою модель. Как я могу улучшить это?


person Francisco Dibar    schedule 28.06.2018    source источник
comment
Какой вывод вы получаете для второй строки? Я запустил ваш код и получил Ok { code = Nothing } для второй строки.   -  person Dogbert    schedule 28.06.2018
comment
Ваш декодер у меня работает. Обратите внимание, что dec0 можно сократить до Decode.list dec1 |> Decode.map List.head.   -  person Chad Gilbert    schedule 28.06.2018
comment
Рабочий пример вашего кода находится по адресу ellie-app.com/D8WTFxc73Sa1.   -  person bdukes    schedule 28.06.2018
comment
Вы, ребята, правы, это работает для обоих случаев, я добавил третий, который является проблематичным.   -  person Francisco Dibar    schedule 28.06.2018


Ответы (1)


Более упрощенный подход может использовать Json.Decode.index для принудительного декодирования нулевого индекса в виде строки, если она существует, что в противном случае приведет к сбою, поэтому вы можете использовать Json.Decode.maybe для возврата Nothing в случае ошибки.

dec0 =
    Decode.maybe (Decode.index 0 dec1)
person Chad Gilbert    schedule 28.06.2018