# JSON Package

The `json` package provides the [JsonDoc](json-JsonDoc) class both as a container for a JSON
document and as means of parsing from and writing to [String](builtin-String).

## JSON Representation

JSON is represented in Pony as the following types:

* object - [JsonObject](json-JsonObject)
* array  - [JsonArray](json-JsonArray)
* string - [String](builtin-String)
* integer - [I64](builtin-I64)
* float   - [F64](builtin-F64)
* boolean - [Bool](builtin-Bool)
* null    - [None](builtin-None)

The collection types JsonObject and JsonArray can contain any other JSON
structures arbitrarily nested.

[JsonType](json-JsonType) is used to subsume all possible JSON types. It can
also be used to describe everything that can be serialized using this package.

## Parsing JSON

For getting JSON from a String into proper Pony data structures,
[JsonDoc.parse](json-JsonDoc#parse) needs to be used. This will populate the
public field `JsonDoc.data`, which is [None](builtin-None), if [parse](json-JsonDoc#parse) has
not been called yet.

Every call to [parse](json-JsonDoc#parse) overwrites the `data` field, so one
JsonDoc instance can be used to parse multiple JSON Strings one by one.

```pony
let doc = JsonDoc
// parsing
doc.parse(\"\"\"{"key":"value", "property: true, "array":[1, 2.5, false]}\"\"\")?

// extracting values from a JSON structure
let json: JsonObject  = doc.data as JsonObject
let key: String       = json.data("key")? as String
let property: Boolean = json.data("property")? as Bool
let array: JsonArray  = json.data("array")?
let first: I64        = array.data(0)? as I64
let second: F64       = array.data(1)? as F64
let last: Bool        = array.data(2)? as Bool
```

### Sending JSON

[JsonDoc](json-JsonDoc) has the `ref` reference capability, which means it is
not sendable by default. If you need to send it to another actor you need to
recover it to a sendable reference capability (either `val` or `iso`). For the
sake of simplicity it is recommended to do the parsing already in the recover
block:

```pony
// sending an iso doc
let json_string = \"\"\"{"array":[1, true, null]}\"\"\"
let sendable_doc: JsonDoc iso = recover iso JsonDoc.>parse(json_string)? end
some_actor.send(consume sendable_doc)

// sending a val doc
let val_doc: JsonDoc val = recover val JsonDoc.>parse(json_string)? end
some_actor.send_val(val_doc)
```

When sending an `iso` JsonDoc it is important to recover it to a `ref` on the
receiving side in order to be able to properly access the json structures in
`data`.

## Writing JSON

JSON is written using the [JsonDoc.string](json-JsonDoc#string) method. This
will serialize the contents of the `data` field to [String](builtin-String).

```pony
// building up the JSON data structure
let doc = JsonDoc
let obj = JsonObject
obj.data("key") = "value"
obj.data("property") = true
obj.data("array") = JsonArray.from_array([ as JsonType: I64(1); F64(2.5); false])
doc.data = obj

// writing to String
env.out.print(
  doc.string(where indent="  ", pretty_print=true)
)

```


## Public Types

* [type JsonType](json-JsonType.md)
* [class JsonArray](json-JsonArray.md)
* [class JsonObject](json-JsonObject.md)
* [class JsonDoc](json-JsonDoc.md)


## Private Types

* [primitive _JsonPrint](json-_JsonPrint.md)
