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
Argonaut is a library for working with JSON in PureScript. `argonaut-codecs` provides codecs based on the `EncodeJson` and `DecodeJson` type classes, along with instances for common data types and combinators for encoding and decoding `Json` values.
9
+
[Argonaut](https://github.com/purescript-contrib/purescript-argonaut) is a collection of libraries for working with JSON in PureScript. `argonaut-codecs` provides codecs based on the `EncodeJson` and `DecodeJson` type classes, along with instances for common data types and combinators for encoding and decoding `Json` values.
10
10
11
11
## Installation
12
12
13
+
This library is bundled as part of [Argonaut](https://github.com/purescript-contrib/purescript-argonaut) and can be installed via that library. To install just `argonaut-codecs`:
Module documentation is [published on Pursuit](https://pursuit.purescript.org/packages/purescript-argonaut-codecs).
24
-
25
-
You may also be interested in other libraries in the Argonaut ecosystem:
25
+
Module documentation is [published on Pursuit](https://pursuit.purescript.org/packages/purescript-argonaut-codecs). You may also be interested in other libraries in the Argonaut ecosystem:
26
26
27
27
-[purescript-argonaut-core](https://github.com/purescript-contrib/purescript-argonaut-core) defines the `Json` type, along with basic parsing, printing, and folding functions
28
28
-[purescript-argonaut-traversals](https://github.com/purescript-contrib/purescript-argonaut-traversals) defines prisms, traversals, and zippers for the `Json` type.
@@ -49,7 +49,7 @@ userFromJson = decodeJson
49
49
50
50
In a REPL we can see these functions in action:
51
51
52
-
```sh
52
+
```
53
53
> user = { name: "Tom", age: Just 25 }
54
54
> stringify (encodeJson user)
55
55
"{\"name\":\"Tom\",\"age\":25}"
@@ -125,7 +125,7 @@ encodeJson :: EncodeJson a => a -> Json
125
125
126
126
> Tip: There is no `Show` instance for `Json`. To print a `Json` value as a valid JSON string, use `stringify` -- it's the same as the [JavaScript `stringify` method](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify).
127
127
128
-
```sh
128
+
```
129
129
> user = { name: "Tom", age: Just 25, team: Just "Red Team" } :: User
@@ -143,7 +143,7 @@ decodeJson :: DecodeJson a => Json -> Either String a
143
143
144
144
> Tip: To parse a JSON string as a `Json` value, you can use the `jsonParser` function (which can fail). If you are sure you have valid JSON, then consider writing it in an FFI file and foreign importing it as `Json` as described in the [`argonaut-core` documentation](https://github.com/purescript-contrib/purescript-argonaut-core#introducing-json-values).
@@ -155,7 +155,7 @@ Right "{\"name\":\"Tom\",\"age\":25,\"team\":null}"
155
155
156
156
Decoding can fail if the `Json` doesn't match the shape expected by a `DecodeJson` instance; in that case, an error is returned instead of the decoded value.
> (decodeJson =<< jsonParser badUserJsonString) :: Either String User
161
161
Left "JSON was missing expected field: team"
@@ -239,7 +239,7 @@ To recap: manually encoding your data type involves a few steps:
239
239
2. Use `:=` or `:=?` to create a key/value pair in a JSON object
240
240
3. Use `~>` or `~>?` to chain together multiple key/value pairs.
241
241
242
-
Ultimately, this will produce an `Object Json` which can be serialized to a JSON string or manipulated.
242
+
Ultimately, this will produce `Json` which can be serialized to a JSON string or manipulated.
243
243
244
244
#### Decoding JSON
245
245
@@ -274,8 +274,9 @@ If your type can be represented easily with a `String`, `Number`, `Boolean`, or
274
274
275
275
However, quite often your data type will require representation as an object. This library provides combinators in `Data.Argonaut.Decode.Combinators` which are useful for decoding objects into PureScript types by looking up keys in the object and decoding them according to their `DecodeJson` instances.
276
276
277
-
- Use `.:` (`getField`) to decode a field;if the field is missing, this will decode to a `Maybe`
278
-
- Use `.!=` (`defaultField`) to provide a default value for a field which may not exist. If decoding fails, you'll still get an error; if decoding succeeds with a value of type `Maybe a`, then this default value will handle the `Nothing` case.
277
+
- Use `.:` (`getField`) to decode a field where the key must exist; if the field is missing, this will fail with a decoding error.
278
+
- Use `.:?` (`getFieldOptional'`) to decode a field where the key may exist; if the field is missing or its value is `null` then this will return `Nothing`, and otherwise it will attempt to decode the value at the given key.
279
+
- Use `.!=` (`defaultField`) in conjunction with `.:?` to provide a default value for a field which may not exist. If decoding fails, you'll still get an error; if decoding succeeds with a value of type `Maybe a`, then this default value will handle the `Nothing` case.
279
280
280
281
Let's use these combinators to decode a `Json` object into our `AppUser` record.
281
282
@@ -284,22 +285,20 @@ The `decodeJson` function returns an `Either String a` value; `Either` is a mona
284
285
```purs
285
286
instance decodeJsonAppUser :: DecodeJson AppUser where
286
287
decodeJson json = do
287
-
obj <- decodeJson json -- decode `Json` to `Object Json`
288
-
name <- obj .: "name" -- decode the "name" key to a `String`
289
-
age <- obj .: "age" -- decode the "age" key to a `Maybe Int`
290
-
team <- obj .: "team" .!= RedTeam -- decode "team" to `Team`, defaulting to `RedTeam`
291
-
-- if the field is missing or `null`
288
+
obj <- decodeJson json -- decode `Json` to `Object Json`
289
+
name <- obj .: "name" -- decode the "name" key to a `String`
290
+
age <- obj .:? "age" -- decode the "age" key to a `Maybe Int`
291
+
team <- obj .:? "team" .!= RedTeam -- decode "team" to `Team`, defaulting to `RedTeam`
292
+
-- if the field is missing or `null`
292
293
pure $ AppUser { name, age, team }
293
294
```
294
295
295
296
To recap: manually decoding your data type involves a few steps:
296
297
297
298
1. Ensure that all types you are decoding have a `DecodeJson` instance
298
-
299
-
2. Use `.:` to decode object fields
300
-
299
+
2. Use `.:` to decode object fields where the key must exist
300
+
3. Use `.:?` to decode object fields where the key may exist or its value may be null
301
301
3. Use `.!=` to provide a default value for fields which may exist in the `Json`, but must exist in the type you're decoding to (it's like `fromMaybe` for your decoder, unwrapping the decoded value).
302
-
303
302
4. It's common to use the `Either` monad for convenience when writing decoders. Any failed decoding step will abort the entire computation with that error. See [Solving Common Problems](#solving-common-problems) for alternative approaches to decoding.
304
303
305
304
#### Deriving Instances
@@ -479,14 +478,14 @@ decodeUser :: Json -> Either String User
479
478
decodeUser json = do
480
479
obj <- decodeJson json
481
480
name <- obj .: "name"
482
-
age <- obj .: "age"
481
+
age <- obj .:? "age"
483
482
location <- obj .: "location"
484
483
pure $ User { name, age, location }
485
484
```
486
485
487
486
Running this in the REPL with bad input, we only see the first error:
0 commit comments