Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
kintrix007 opened this issue Jun 11, 2024 · 1 comment · May be fixed by #35
Open

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

kintrix007 opened this issue Jun 11, 2024 · 1 comment · May be fixed by #35

Comments

@kintrix007
Copy link

kintrix007 commented Jun 11, 2024

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
Copy link
Author

If #25 gets resolved I would be more than happy to implement this and write documentation on it, maybe in a similar style to oneOf.

I looked into implementing something like what #25 proposes, but ultimately I do not (yet) understand how the Kernel of Elm works and how to add to it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant