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

replace getRandomCatGif with getRandomQuote #287

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 4 additions & 12 deletions book/effects/json.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,8 +147,7 @@ This example is pretty similar to the last one:
- `update` handles the `GotQuote` message for whenever a new quote is available. Whatever happens there, we do not have any additional commands. It also handles the `MorePlease` message when someone presses the button, issuing a command to get more random quotes.
- `view` shows you the quotes!

The main difference is in the `getRandomCatGif` definition. Instead of using `Http.expectString`, we have switched to `Http.expectJson`. What is the deal with that?

The main difference is in the `getRandomQuote` definition. Instead of using `Http.expectString`, we have switched to `Http.expectJson`. What is the deal with that?

## JSON

Expand All @@ -169,15 +168,14 @@ In JavaScript, the approach is to just turn JSON into JavaScript objects and hop

In Elm, we validate the JSON before it comes into our program. So if the data has an unexpected structure, we learn about it immediately. There is no way for bad data to sneak through and cause a runtime exception three files over. This is accomplished with JSON decoders.


## JSON Decoders

Say we have some JSON:

```json
{
"name": "Tom",
"age": 42
"name": "Tom",
"age": 42
}
```

Expand All @@ -193,7 +191,6 @@ If all goes well, we get a `String` on the other side!

How do we create decoders like this though?


## Building Blocks

The [`elm/json`][json] package gives us the [`Json.Decode`][decode] module. It is filled with tiny decoders that we can snap together.
Expand Down Expand Up @@ -237,7 +234,6 @@ In this case we demand an object with a `"name"` field, and if it exists, we wan

[field]: https://package.elm-lang.org/packages/elm/json/latest/Json-Decode#field


## Combining Decoders

But what if we want to decode _two_ fields? We snap decoders together with [`map2`](https://package.elm-lang.org/packages/elm/json/latest/Json-Decode#map2):
Expand Down Expand Up @@ -267,7 +263,6 @@ So if we used `personDecoder` on `{ "name": "Tom", "age": 42 }` we would get out

If we really wanted to get into the spirit of decoders, we would define `personDecoder` as `map2 Person nameDecoder ageDecoder` using our previous definitions. You always want to be building your decoders up from smaller building blocks!


## Nesting Decoders

A lot of JSON data is not so nice and flat. Imagine if `/api/random-quotes/v2` was released with richer information about authors:
Expand All @@ -276,8 +271,7 @@ A lot of JSON data is not so nice and flat. Imagine if `/api/random-quotes/v2` w
{
"quote": "December used to be a month but it is now a year",
"source": "Letters from a Stoic",
"author":
{
"author": {
"name": "Seneca",
"age": 68,
"origin": "Cordoba"
Expand Down Expand Up @@ -320,7 +314,6 @@ personDecoder =

Notice that we do not bother decoding the `"origin"` field of the author. Decoders are fine with skipping over fields, which can be helpful when extracting a small amount of information from very large JSON values.


## Next Steps

There are a bunch of important functions in `Json.Decode` that we did not cover here:
Expand All @@ -334,5 +327,4 @@ So there are ways to extract all sorts of data structures. The `oneOf` function

We saw [`map2`](https://package.elm-lang.org/packages/elm/json/latest/Json-Decode#map2) and [`map4`](https://package.elm-lang.org/packages/elm/json/latest/Json-Decode#map4) for handling objects with many fields. But as you start working with larger and larger JSON objects, it is worth checking out [`NoRedInk/elm-json-decode-pipeline`](https://package.elm-lang.org/packages/NoRedInk/elm-json-decode-pipeline/latest). The types there are a bit fancier, but some folks find them much easier to read and work with.


> **Fun Fact:** I have heard a bunch of stories of folks finding bugs in their _server_ code as they switched from JS to Elm. The decoders people write end up working as a validation phase, catching weird stuff in JSON values. So when NoRedInk switched from React to Elm, it revealed a couple bugs in their Ruby code!