You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
When receiving JSON data from other resources(server API etc), we need Json.Decoder to convert the JSON values into Elm values. This cheatsheet is to let you quickly learn how to do that.
When receiving JSON data from other resources(server API etc), we need [Json.Decode](http://package.elm-lang.org/packages/elm-lang/core/3.0.0/Json-Decode) to convert the JSON values into Elm values. This gist let you quickly learn how to do that.
To show you working code, this is how the boilerplate will look like:
I like to follow working example code so this is how the boilerplate will look like:
```elm
importGraphics.Elementexposing (Element, show)
yang-wei
renamed
this gist Mar 1, 2016.
1 changed file
with
0 additions
and
2 deletions.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
When receiving JSON data from other resources(server API etc), we need Json.Decoder to convert the JSON values into Elm values. This cheatsheet is to let you quickly learn how to do that.
To show you working code, this is how the boilerplate will look like:
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
When receiving JSON data from other resources(server API etc), we need Json.Decoder to convert the JSON values into Elm values. This cheatsheet is to let you quickly learn how to do that.
To show you working code, this is how the boilerplate will look like:
-- initialize mailbox with the type declared above
mailbox =
Signal.mailbox (SimpleRecord"""")
-- VIEW
main:SignalElement
main =
Signal.map show mailbox.signal
-- TASK
fetchApi =
Http.get decoder api
handleResponse data =
Signal.send mailbox.address data
-- decoder changes depends on our data type
decoder =...
port run:TaskHttp.Error()
port run =
fetchApi `andThen` handleResponse
api =
"http://some-api-url.com"
```
So here we have a mailbox - `mailbox` which contains initial data depending on the data type. When the application starts, `fetch` is called and the response is handled by `handleResponse`. Our `main` function will display the value of `mailbox` value.
Here, we will fetch data github api and display it on screen. So to follow along this tutorial, you have to modify
1. data type (currently SimpleRecord)
2. initial data in `mailbox`
3. decoder function
4. api (to get different data)
Notice that I am omitting some data annotations for brevity. Our main focus in this post will be `decoder` function. We will see how to utilize the Json.Decoder library when dealing with different type of data.
## Objects
### Object -> tuple
First of all let's fetch the elm-lang/core repository. The API looks like:
```
https://api.github.com/repos/elm-lang/core
```
If you paste this on browser, you will see something like:
```json
{
"id": 25231002,
"name": "core",
...
"subscribers_count": 47
}
```
Let's say we are interested in 3 fields - `name`, `description` and `watchers_count` of this repository and we want to display it in simple tuple: ie (name, description, watchers_count).
Here is how our data type looks like:
```elm
type alias RepoTuple=(String,String,Int)
mailbox =
Signal.mailbox ("","",0)
```
We also need to declare the initial data in mailbox - ("", "", 0).
Because our API returns a JSON object, the Object fields in [doc](http://package.elm-lang.org/packages/elm-lang/core/3.0.0/Json-Decode#) will give us what we need. In our case we need 3 fields, so we will use `object3`. Elm supports `object1` to `object8` and we have to decide depends on how many value we need.
```elm
object3
:(a -> b -> c -> value)
->Decoder a
->Decoder b
->Decoder c
->Decoder value
```
The first argument `(a -> b -> c -> value)` is a function which takes 3 arguments and return a `value`. In Elm, we know that
```elm
(,,)"Name""Description"100
-- ("Name","Description",100) : ( String, String, number )
```
So our decoder would be:
```elm
repoTupleDecoder:DecoderRepoTuple
repoTupleDecoder =
object3 (,,)
("name":= string)
("description":= string)
("watchers_count":= int)
```
The `:=` operator is use to extract the field with the given name. Since we are interested in name, description and watchers_count so we declare it explicitly and state it's type.
```elm
fetchApi =
Http.get repoTupleDecoder api
```
And this is the [working code](https://gist.github.com/yang-wei/2d1c33b9c114fcd652ff#file-repotuple-elm) for this example.
### Object -> record
Often tuple doesn't give enough information, in most case we want to preserve the value of field itself. So our type will look like:
```elm
type alias RepoRecord=
{ name :String
, description :String
, watchers_count :Int
}
mailbox =
Signal.mailbox (RepoRecord""""0)
```
Note that in this case our data type is Record so we can initialize it by `RepoRecord "" "" 0` which will return `{ name = "", description = "", watchers_count = 0 }` which is cool. What cooler is we can even reuse it in our decoder:
```elm
repoRecordDecoder:DecoderRepoRecord
repoRecordDecoder =
object3 RepoRecord
("name":= string)
("description":= string)
("watchers_count":= int)
```
Do remember to change the function name in `fetchApi`:
```elm
fetchApi =
Http.get repoRecordDecoder api
```
Now we will get a nice record:
```elm
{ name ="core", description ="Elm's core libraries", watchers_count =338}
```
Again, for your reference the source is [here](https://gist.github.com/yang-wei/2d1c33b9c114fcd652ff#file-repotuple-elm).
### Nested Object
When we hit the [API](https://api.github.com/repos/elm-lang/core), it returns an object which contains the owner of repository in a nested object.
Let's look at how we can retrive the value in **owner** object. We can of course create nested decoder by using 2 times of `object3` but we can avoid this by using `[at](http://package.elm-lang.org/packages/elm-lang/core/3.0.0/Json-Decode#at)`
```elm
at:ListString->Decodera->Decodera
```
Changing everything we need:
```elm
type alias OwnerRecord=
{ login :String
, id :Int
, avatar_url :String
}
mailbox =
Signal.mailbox (OwnerRecord""-1"")
```
Because the data we need have only single layer of nested field, so the first argument passed to `at` only has one value, that is `["owner"]`.
Besides `keyValuePairs`, we also has `[Decoder.dict](http://package.elm-lang.org/packages/elm-lang/core/3.0.0/Json-Decode#dict)` to turn object into dictionary.
```elm
type alias Languages=
DictStringInt
mailbox =
Signal.mailbox Dict.empty
decoder:Decoder (DictStringInt)
decoder =
dict int
```
## Arrays
### Array -> tuple
In the previous section, we had seen multiples way to deal with object typed JSON value. However sometimes, we have an array. For example:
The field we are particularly interested in is the items field. Let's say we want a list which contains the `full_name` of the Elm repository.
```elm
["elm-lang/elm-lang.org","elm-lang/core"...]
```
Let's initialize our data first:
```elm
mailbox =
Signal.mailbox []
```
First of all, here is our decoder to extract the `full_name` value
```elm
fullNameDecoder:DecoderString
fullNameDecoder =
object1 identity ("full_name":= string)
```
Because our data is nested in the `items` field, we have to access it using the `at` operator (hope you still remember):
```elm
decoder =
at ["items"] _
```
The `items` will give us an array which contains object, so we will use `[Decoder.list](http://package.elm-lang.org/packages/elm-lang/core/3.0.0/Json-Decode#list)`:
```elm
list:Decodera->Decoder (Lista)
```
`Decoder.list` takes a decoder and returns another decoder which can handle list. This suits our case:
```
decoder =
at ["items"] (list fullNameDecoder)
```
Now if you wish to also extract other fields, you just have to change your `fullNameDecoder`. The source of this example is shown [here](https://gist.github.com/yang-wei/2d1c33b9c114fcd652ff#file-listdecoder-elm).