Я согласен, что факт Json.Decode.maybe
, который дает вам Nothing
на неправильном значении, а не на пропущенном одном, удивителен.
elm-json-decode-pipeline
может работать так, как вы хотите, не слишком многословно.
> d = Decode.succeed Point
| |> optional "2" (Decode.float |> Decode.map Just) Nothing
| |> required "1" Decode.float
| |> required "0" Decode.float
|
> "[1, 2, \"3\"]" |> Decode.decodeString d
Err (Failure ("Json.Decode.oneOf failed in the following 2 ways:\n\n\n\n(1) Problem with the given value:\n \n \"3\"\n \n Expecting a FLOAT\n\n\n\n(2) Problem with the given value:\n \n \"3\"\n \n Expecting null") <internals>)
: Result Decode.Error Point
> "[1, 2, 3]" |> Decode.decodeString d
Ok { at = 2, elev = Just 3, lng = 1 }
: Result Decode.Error Point
> "[1, 2]" |> Decode.decodeString d
Ok { at = 2, elev = Nothing, lng = 1 }
: Result Decode.Error Point
(из ошибки видно, что под капотом он использует oneOf
как в glennsl's ответ .)
Единственная потенциально удивительная вещь здесь - это то, что вам нужно передавать строки, а не индексы int, так как не существует определенной c версии для списков, но вы можете получить доступ к индексам списков как хотя они являются именами полей. Это означает, что эта версия немного отличается тем, что она не выдаст ошибку, если вы можете создать объект с именами числовых полей, а не массивом, но я не могу представить, что это действительно проблема. Более реальная проблема - это может сделать ваши сообщения об ошибках менее точными:
> "[0]" |> Decode.decodeString (Decode.field "0" Decode.int)
Ok 0 : Result Decode.Error Int
> "[]" |> Decode.decodeString (Decode.field "0" Decode.int)
Err (Failure ("Expecting an OBJECT with a field named `0`") <internals>)
: Result Decode.Error Int
> "[]" |> Decode.decodeString (Decode.index 0 Decode.int)
Err (Failure ("Expecting a LONGER array. Need index 0 but only see 0 entries") <internals>)
Обратите внимание, что вам все равно нужно избегать использования Json.Decode.maybe
. Может быть заманчиво написать optional "2" (Decode.maybe Decode.float) Nothing
, что приведет к тому же поведению, что и вы изначально.