Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Elm: How to decode data from JSON API

Tags:

json

elm

I have this data using http://jsonapi.org/ format:

{
    "data": [
        {
            "type": "prospect",
            "id": "1",
            "attributes": {
                "provider_user_id": "1",
                "provider": "facebook",
                "name": "Julia",
                "invitation_id": 25
            }
        },
        {
            "type": "prospect",
            "id": "2",
            "attributes": {
                "provider_user_id": "2",
                "provider": "facebook",
                "name": "Sam",
                "invitation_id": 23
            }
        }
    ]
}

I have my models like:

type alias Model = {
  id: Int,
  invitation: Int,
  name: String,
  provider: String,
  provider_user_id: Int
 }

 type alias Collection = List Model

I want to decode the json into a Collection, but don't know how.

fetchAll: Effects Actions.Action
fetchAll =
  Http.get decoder (Http.url prospectsUrl [])
   |> Task.toResult
   |> Task.map Actions.FetchSuccess
   |> Effects.task

decoder: Json.Decode.Decoder Collection
decoder =
  ?

How do I implement decoder? Thanks

like image 457
Sebastian Avatar asked Sep 14 '15 22:09

Sebastian


People also ask

Can I decode a JSON string into an elm record?

The price of gaining this confidence when decoding JSON is stiff. You will need to tell Elm how it should turn the JSON string into an Elm record so that it can play nicely with it later, as it would with other Elm type aliases.

What data types does Elm support for JSON?

Elm provides three other decoders for translating primitive JSON types to Elm values: int, float, and bool. Here are some examples showing them in action: JSON supports the following data types: string — A string must be written in double quotes and looks very similar to an Elm string.

How does the decodestring function work in Elm?

The decodeString function is the one that does the actual decoding. It first parses the raw string into JSON and then applies the string decoder to translate that JSON into an Elm string. The following diagram explains the type signature of decodeString in detail. When decoding fails, decodeString returns a value of type Error.

What decoders are available for primitive JSON types?

Elm provides three other decoders for translating primitive JSON types to Elm values: int, float, and bool. Here are some examples showing them in action:


1 Answers

N.B. Json.Decode docs

Try this:

import Json.Decode as Decode exposing (Decoder)
import String

-- <SNIP>

stringToInt : Decoder String -> Decoder Int
stringToInt d =
  Decode.customDecoder d String.toInt

decoder : Decoder Model
decoder =
  Decode.map5 Model
    (Decode.field "id" Decode.string |> stringToInt )
    (Decode.at ["attributes", "invitation_id"] Decode.int)
    (Decode.at ["attributes", "name"] Decode.string)
    (Decode.at ["attributes", "provider"] Decode.string)
    (Decode.at ["attributes", "provider_user_id"] Decode.string |> stringToInt)

decoderColl : Decoder Collection
decoderColl =
  Decode.map identity
    (Decode.field "data" (Decode.list decoder))

The tricky part is using stringToInt to turn string fields into integers. I've followed the API example in terms of what is an int and what is a string. We luck out a little that String.toInt returns a Result as expected by customDecoder but there's enough flexibility that you can get a little more sophisticated and accept both. Normally you'd use map for this sort of thing; customDecoder is essentially map for functions that can fail.

The other trick was to use Decode.at to get inside the attributes child object.

like image 121
mgold Avatar answered Oct 05 '22 19:10

mgold