json
json copied to clipboard
Add function to parse JSON string as a number instead. ("42" -> 42)
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.