Elm 如何使用可选元素制作解码器?

Elm 如何使用可选元素制作解码器?,elm,decoder,Elm,Decoder,我一直在使用一个解码器,它应该将数组[9.34958,48.87733,1000]解码到点,其中索引2(高程)是可选的 type alias Point = { elev : Maybe Float , at : Float , lng : Float } 因此,我创建了以下解码器: fromArrayDecoder : Decoder Point fromArrayDecoder = map3 Point (index 2 Decode

我一直在使用一个解码器,它应该将数组
[9.34958,48.87733,1000]
解码到
点,其中索引2(高程)是可选的

type alias Point =
    { elev : Maybe Float
    , at : Float
    , lng : Float
    }
因此,我创建了以下解码器:

fromArrayDecoder : Decoder Point
fromArrayDecoder =
    map3 Point
        (index 2 Decode.float |> Decode.maybe)
        (index 1 Decode.float)
        (index 0 Decode.float)
我现在的问题是,当索引2丢失或是字符串等任何类型时,解码器都会成功。但我只希望它在elev丢失时成功,而不是在它的类型错误时成功。有什么方法可以做到这一点吗?

如果“缺少”的意思是值可以是
null
,那么您可以使用而不是
或者

fromArrayDecoder : Decoder Point
fromArrayDecoder =
  map3 Point
    (index 2 Decode.float |> Decode.nullable)
    (index 1 Decode.float)
    (index 0 Decode.float)
如果是三元素数组或两元素数组,您可以按顺序使用多个解码器:

fromTwoArrayDecoder : Decoder Point
fromTwoArrayDecoder =
  map3 (Point Nothing)
    (index 1 Decode.float)
    (index 0 Decode.float)

fromThreeArrayDecoder : Decoder Point
fromThreeArrayDecoder =
  map3 Point
    (index 2 Decode.float |> Decode.map Just)
    (index 1 Decode.float)
    (index 0 Decode.float)

fromArrayDecoder : Decoder Point
fromArrayDecoder =
  oneOf
    [ fromThreeArrayDecoder
    , fromTwoArrayDecoder
    ]

请记住首先尝试3元素解码器,因为2元素解码器在3元素阵列上也会成功,但事实并非如此。

我同意事实
Json.Decode。也许
在错误的值上给你
什么都不给你,而不仅仅是一个缺少的值,这是令人惊讶的

可以按照您想要的方式工作,而不会太冗长

> 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
请注意,您仍然必须避免使用
Json.Decode.maybe
。可能很容易编写
可选的“2”(Decode.maybe Decode.float)而不编写任何内容
,这将导致与您最初得到的行为相同。

您所说的“缺失”是什么意思?是
null
,还是在这种情况下数组只有两个元素?
> "[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>)