For the complete documentation index, see llms.txt. This page is also available as Markdown.

Key Emission

When a member is written as a bare value and when it is written as key -- value.

For every member a writer emits, it makes one decision: write the value alone, or write key: value. This page defines that decision. It is the single largest source of drift between implementations, so the rule is stated as a table rather than prose.

Recoverable and unrecoverable names

A member's name is recoverable when a reader can reconstruct it without seeing it in the data — because a schema in scope declares it at that position. A recoverable name is redundant on the wire and is omitted.

A name is unrecoverable when no schema in scope declares it. It MUST be written inline, or the value cannot be read back.

Two members never carry a name at all:

  • a keyless (positional) member — it had no name to begin with;

  • a member whose key equals its own ordinal index ("0" in slot 0) — position already says it.

The three modes

A writer offers three key-emission modes. extras is the default and is the only mode that is lossless in every case.

Mode
Meaning

none

Never write a key. Values only — leanest, and lossy when a name is unrecoverable.

extras (default)

Write a key only when the name is unrecoverable. Lossless.

all

Write a key for every named member. Fully self-describing, larger output.

The decision table

Member

none

extras (default)

all

keyless / positional

bare

bare

bare

declared by a schema in scope

bare

bare

key: value

not declared — an extensible schema's extra, or no schema at all

bare (lossy)

key: value

key: value

not declared, schema is closed

error

error

error

The last row is a validation failure, not a formatting choice: a strict schema has no place to put the member, so the writer MUST raise unknown-member rather than emit something that will not read back.

Examples

With a schema in scope, declared members are positional; only the mode changes that:

With no schema, every name is unrecoverable, so extras writes them all:

Under an open schema, declared members stay positional and extras are named:

A keyless member is always bare, and an explicit non-index key always survives:

Mode none is lossy by design, for endpoints that already agree on every name. A writer SHOULD NOT use it as a default, and MUST NOT use it when any name is unrecoverable and the output is intended to round-trip.

Depth

The mode applies at every nesting level: in all, a nested member declared by its parent's shape is also written key: value; in extras, a nested extra is named just as a record-level extra is.

Objects reached through an array are no exception — each element is keyed by its own shape.

Ordering

Members are written in schema order when a schema is in scope: each declared member in the order the schema declares it, followed by any extras in the order they appear in the value. Without a schema, members are written in the order the value holds them.

This is the writer's half of one rule. The reader's half — that a declared member OCCUPIES that position in the loaded value, however the document wrote it — is Member position. A writer that emits schema order from a value model that did not enforce it would produce correct text from an object whose own getAt(1) disagreed with it.

A declared member that is absent, optional, and has no default MUST still hold its position — see Record & Document Output.

See Also

Last updated

Was this helpful?