### [json-decode] And [json-encode]: JSON Data in Pd

Home

Pd does not have boolean values, and no notion of a NULL object, only lists, symbols (=strings) and floats (=numbers).

To use the definitions from json.org this leads to the following mapping of JSON data to Pd:

JSON type | Pd type | JSON example | Pd example
--- | --- | --- | ---
string | symbol | "my string, containing a comma" | symbol my string\, containing a comma
number | float | 1.01 | 1.01
object | see below | {"key": "value"} |
array | see below | [{"key": "value"}, {"other key": "other value"}] |
boolean | float | true | 1
null | symbol | null | symbol

As you can infer from the table, values of `true`, `false`, or `null` cannot be constructed by `[json-encode]`, but can be read by the objects. A value of null yields a Pd value of an empty symbol.

## `[json-decode]`

Feeding a symbol or list to `[json-decode]` will parse the values and generate an output. If you use a list, then all elements of the list will be converted to symbols and concatenated using a space as separator, so `symbol my value` will generate the same output as `list my value`.

You must feed exactly one valid JSON object or array of objects as a symbol or list message to `[json-decode]`. Any other correct JSON data cannot be interpreted by the `[json-decode]`.

### Output of a JSON object

JSON objects are interpreted by `[json-decode]` as key value stores. Each key/value pair outputs a list on the left outlet, where the key is always converted to a symbol, while the value is converted according to the table above. Arrays and objects are converted to their string representation again and then output as a symbol.

After all key/value are sent to the left outlet, a `bang` is emitted from the right outlet.

Example:

JSON string:

    {
      "id": 1,
      "active": true,
      "obsolete": false,
      "name": "PuREST JSON",
      "objects": ["json-decode", "json-encode", "urlparams", "rest", "oauth"],
      "author": {"name": "me", "age": "none of your business"}
    }

Output:

1. left: `list id 1`
2. left: `list active 1`
3. left: `list obsolete 0`
4. left: `list name PuREST JSON`
5. left: `list objects ["json-decode"\, "json-encode"\, "urlparams"\, "rest"\, "oauth"]`
6. left: `list author {"name": "me"\, "age": "none of your business"}`
7. right: `bang`

### Output of an Array of JSON objects

An array generates the same output as a series of JSON objects, including `bang` messages on the right outlet.

Example:

JSON string:

    [
      {"key": "value", "id": 1},
      {"id": 2},
      {"id": 3}
    ]

Output:

1. left: `list key value`
2. left: `list id 1`
3. right: `bang`
4. left: `list id 2`
5. right: `bang`
6. left: `list id 3`
7. right: `bang`

### Some hints for data processing

- Use `list trim` from list-abs for trimming the list selector off the output and then use `[route]` for the data. If you want to create new lists, feed them into `[pack]`.
- If you process an array of same object types, use the approach above and store the values in a FIFO buffer, e. g. `[fifop]` from zexy or `[list-fifo]` from list-abs.
- Do not expect JSON data to be ordered: `{"id": 1, "name: "my name"}` and `{"name": "my name", "id": 1}` are in fact the same object. Use an empty first inlet of `[pack]` and the `bang` from the right outlet to create your own lists.

## `[json-encode]`

### Reading and Writing JSON files

`[json-encode]` can hold one JSON object at a time in its memory. Therefore, if you read JSON data from a file using the `[read(` message, the message needs exactly one additional parameter, the path to the file to read.

The file must contain exactly one JSON object. If you want to read an array, you must wrap the array in an object.

Example:

`[{"key": "value"}, {"another key": "another value"}]` cannot be read, but `{"wrapping": [{"key": "value"}, {"another key": "another value"}]}` can.

To write data to a file, use the `[write(` message. This message needs exactly one additional parameter, the path to the file to write the JSON object as string. It will overwrite existing content without asking for confirmation.

### Storing Data with `[add(` And `[array(`

There are two messages for adding values to the JSON object stored in `[json-encode]`, `[add(` and `[array(`. Both need at least two additional values. The first parameter must be a symbol and represents the key. As Pd currently has no way to escape whitespace, there is no simple way to generate keys with space in it, a workaround is possible using `[makefilename]` from zexy.

If the message has exactly two additional parameters, and the second parameter is a float, then the value will be stored as a number. Otherwise all additional parameters will be concatenated with a space.

If the additional parameters can be converted to a JSON object, then the resulting string will be converted thusly, otherwise, a string is stored.

Adding a value with an already stored key will result in overwriting the existing value.

Example: - `[add key 1(` will store `{"key":1}`. - `[add key first second third(` will store `{"key":"first second third"}`. - `[add key {"first":"second third"}(` will store `{"key":{first: "second third"}}`.

`[array(` will add data to an array with the name of the key. The members of the array will be sorted in the specified order. If a value with the same key exists, but was stored with `[add(`, the value will be discarded. A new `[add(` message with the same key will discard the stored array.

Example:

1. `[add id 1(` => `{"id": 1}`.
2. `[array id 2(` => `{"id": [2]}`.
3. `[array id 3(` => `{"id": [2, 3]}`.
4. `[add id 4(` => `{"id": 4}`.

### Outputting And Clearing Data

Issuing a `[bang(` message to `[json-encode]` will output the JSON object as a string on its only outlet. If no data is stored, an empty symbol is sent.

You can clear the stored object with the `[clear(` method.