Home Explore Blog CI



nix

1st chunk of `doc/manual/source/development/json-guideline.md`
68fb791a71819f05b1f1218279c668657f25d11defd8e2f400000001000008cc
# JSON guideline

Nix consumes and produces JSON in a variety of contexts.
These guidelines ensure consistent practices for all our JSON interfaces, for ease of use, and so that experience in one part carries over to another.

## Extensibility

The schema of JSON input and output should allow for backwards compatible extension.
This section explains how to achieve this.

Two definitions are helpful here, because while JSON only defines one "key-value" object type, we use it to cover two use cases:

 - **dictionary**: a map from names to value that all have the same type.
   In C++ this would be a `std::map` with string keys.

 - **record**: a fixed set of attributes each with their own type.
   In C++, this would be represented by a `struct`.

It is best not to mix these use cases, as that may lead to incompatibilities when the schema changes.
For example, adding a record field to a dictionary breaks consumers that assume all JSON object fields to have the same meaning and type, and dictionary items with a colliding name can not be represented anymore.

This leads to the following guidelines:

 - The top-level (root) value must be a record.

   Otherwise, one can not change the structure of a command's output.

 - The value of a dictionary item must be a record.

   Otherwise, the item type can not be extended.

 - List items should be records.

   Otherwise, one can not change the structure of the list items.

   If the order of the items does not matter, and each item has a unique key that is a string, consider representing the list as a dictionary instead.
   If the order of the items needs to be preserved, return a list of records.

 - Streaming JSON should return records.

   An example of a streaming JSON format is [JSON lines](https://jsonlines.org/), where each line represents a JSON value.
   These JSON values can be considered top-level values or list items, and they must be records.

### Examples

This is bad, because all keys must be assumed to be store types:

```json
{
  "local": { ... },
  "remote": { ... },
  "http": { ... }
}
```

This is good, because the it is extensible at the root, and is somewhat self-documenting:

```json
{
  "storeTypes": { "local": { ... }, ... },
  "pluginSupport": true

Title: JSON Guidelines: Extensibility
Summary
This section details guidelines for ensuring backward compatible extension in Nix JSON input and output. It emphasizes distinguishing between dictionaries (maps with same-type values) and records (fixed attributes with different types). The guidelines advise that top-level values, dictionary items, and list items should be records to allow for schema changes, and stream JSON should return records. Examples are provided to illustrate good and bad practices.