是否有一种简单的方法可以使Elm(0.18)中的Json.Decode大小写不敏感?
decodeDepartmentDate : Json.Decode.Decoder DepartmentDate
decodeDepartmentDate =
Json.Decode.map6 DepartmentDate
(field "nameOfDay" Json.Decode.string)
(field "orderDate" Convert.datePart)
(field "mealTimeID" Json.Decode.string)
(field "mealTime" Json.Decode.string)
(field "departmentID" Json.Decode.string)
(field "department" Json.Decode.string)
我希望能够针对多个后端使用相同的elm SPA,并且默认情况下避免此类问题:
BadPayload "Expecting an object with a field named `nameOfDay` at _[11]
but instead got: {\"NameOfDay\":\"Wednesday\",\"OrderDate\":\"2018-09-05T00:00:00\",
\"MealTimeID\":\"546ccee0-e070-403e-a15b-63f4e1366054\",\"MealTime\":\"All Day\",
\"StartTime\":\"2018/06/05 05:04:38\",\"DepartmentID\":\"066a1c9f-97da-487e-b82f-f933b159c042\",
\"Department\":\"Side walk\"}"
谢谢
答案 0 :(得分:2)
据我所知,尚无现成的解决方案。但是你可以自己做!
最简单的方法可能是生成不同的大小写并使用field
制作自己的oneOf
解码器:
myField name decoder =
Decode.oneOf
[ Decode.field name decoder
, Decode.field (String.toLower) decoder
]
另一种方法是将对象解码为键/值对,而不解码值,先转换键,然后再对其进行编码,以能够使用其上的现有JSON解码器:
lowerCaseKeys =
Decode.keyValuePairs Decode.value
|> Decode.map (List.map (\(key, value) -> (String.toLower key, value)))
|> Decode.map (Encode.object)
但是由于现在值被包装在Decoder
中,因此您必须在其上使用decodeValue
并最终以双重包装的Result
结束,这不是很很好但是我可能会缺少一些优雅的方法来完成这项工作。
相反,最好不要对其进行重新编码,而只需使自己的field
解码器即可处理该字典。这也使您可以忽略指定键上的大小写。
lowerCaseKeys : Decode.Decoder (Dict.Dict String Decode.Value)
lowerCaseKeys =
Decode.keyValuePairs Decode.value
|> Decode.map (List.map (\( key, value ) -> ( String.toLower key, value )))
|> Decode.map Dict.fromList
myField : String -> Decode.Decoder a -> Dict.Dict String Decode.Value -> Decode.Decoder a
myField name decode dict =
case Dict.get (String.toLower name) dict of
Just value ->
case Decode.decodeValue decode value of
Ok v ->
Decode.succeed v
Err e ->
e |> Decode.errorToString |> Decode.fail
Nothing ->
Decode.fail "missing key"
result =
Decode.decodeString (lowerCaseKeys |> Decode.andThen (myField "fOO" Decode.int)) """{ "Foo": 42 }"""
答案 1 :(得分:1)
您可以定义field
的变体,而忽略大小写。
fieldInsensitive : String -> Decode.Decoder a -> Decode.Decoder a
fieldInsensitive f d =
let
flow = String.toLower f
in
Decode.keyValuePairs Decode.value |> Decode.andThen
(\ l -> l |> List.filter (\(k, v) -> String.toLower k == flow)
|> List.map (\(k, v) -> v)
|> List.head
|> Maybe.map Decode.succeed
|> Maybe.withDefault (Decode.fail "field not found")
) |> Decode.andThen
(\ v -> case Decode.decodeValue d v of
Ok w -> Decode.succeed w
Err e -> Decode.fail (Decode.errorToString e)
)
这与@glennsl的答案大致相同,但是包含在一个自包含的函数中。优点是界面更简单,缺点是如果您在同一对象中查找多个字段,则会重复工作。
请注意,如果有多个字段具有相同的键(取决于大小写),则此代码将做出相当随意的决定!对于更可靠的代码,如果密钥不止一次存在,则失败可能是一个更好的主意。