Сделайте Json.Decode нечувствительным к регистру в elm

Есть ли простой способ сделать Json.Decode нечувствительным к регистру в elm (0.18)?

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\"}"

Спасибо

Как сделать HTTP-запрос в Javascript?
Как сделать HTTP-запрос в Javascript?
В JavaScript вы можете сделать HTTP-запрос, используя объект XMLHttpRequest или более новый API fetch. Вот пример для обоих методов:
3
0
209
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 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 для работы с dict. Это также позволит вам игнорировать регистр на указанных вами ключах.

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 }"""

Вы можете определить вариант 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, но заключенный в автономную функцию. Преимущество - более простой интерфейс, недостаток - то, что если вы ищете несколько полей в одном и том же объекте, вы будете повторять работу.

Обратите внимание, что этот код принимает довольно произвольное решение, если есть несколько полей с одним и тем же ключом до регистра! Для более надежного кода, возможно, лучше было бы потерпеть неудачу, если ключ существует более одного раза.

Спасибо, искал что-то подобное. Поиграем и посмотрим, как влияет на производительность несколько поисков.

onemorecupofcoffee 03.09.2018 07:10

Другие вопросы по теме