json icon indicating copy to clipboard operation
json copied to clipboard

Add function to parse JSON string as a number instead. ("42" -> 42)

Open kintrix007 opened this issue 8 months ago • 1 comments

The Suggestion

There are cases when the format of the JSON has "sneaky floats/ints". That is, it contains an int or float inside a string instead of a JSON number.

For example:

{
  "foo": "42.0"
}

This is a case where I would want to decode that value to a float. The straightforward solution with the current API is to parse it as a string then convert it to float with String.toFloat. But that leads to something like:

Decode.field "lat" <|
    Decode.map (Maybe.withDefault (0 / 0) << String.toFloat) Decode.string

We need to specify some default value, NaN in this case, or end up with Decoder (Maybe Float). Suboptimal. I want decoding to either fail or result succeed with a Float. A possible solution would be exposing a function, like

stringAs : Decoder value -> Decoder value

Which would allow usage as follows:

Decode.field "lat" <| Decode.stringAs Decode.float

Much nicer, and there is no hidden fail state with a pesky NaN default value.

The Underlying Problem

While it is possible to define something like that in terms of the current public API, doing so loses information about the error. There is no way to create a failing Decoder out of an Error: #25

The current best implementation is something like this:

stringAs : Decode.Decoder value -> Decode.Decoder value
stringAs decoder =
    Decode.string
        |> Decode.andThen
            (\str ->
                case Decode.decodeString decoder str of
                    Err err ->
                        -- If this could be just `Decode.error err` then everything would be solved
                        Decode.fail <| Decode.errorToString err

                    Ok val ->
                        Decode.succeed val
            )

TL;DR:

Please either resolve #25 or add something like stringAs : Decoder a -> Decoder a that parses a JSON string with a different decoder.

kintrix007 avatar Jun 11 '24 21:06 kintrix007