JSON Serialization¶
Field |
Value |
|---|---|
Status |
Draft |
Related RFC |
|
Related drafts |
Message schemas, Error codes, Logical wire message model, Wire requirements, OSC framing, Content representation |
Base standard |
This document defines the initial serialization of one logical protocol Message as UTF-8 JSON. The separate OSC Carrier and Framing document defines how those bytes travel through the terminal stream.
1. One Message, One JSON Object¶
Each logical Message serializes to exactly one JSON object. The object follows
the closed envelope and body schemas selected by its version and kind.
Every Message includes a body object, including messages whose body is empty.
The serialization does not use a top-level array, JSON Lines, a trailing newline, or concatenated JSON values to establish message boundaries. Framing supplies exactly one complete JSON payload to the decoder.
2. UTF-8 and JSON Profile¶
The payload is valid JSON as defined by RFC 8259 and is encoded as UTF-8. A sender does not add a byte-order mark. A receiver rejects invalid UTF-8, a byte-order mark, non-JSON extensions, and any non-whitespace bytes before or after the single JSON object.
Object member names are unique at every nesting level. Duplicate names make the payload invalid rather than selecting the first or last value. Object member order is insignificant. JSON whitespace is permitted wherever RFC 8259 permits it.
Every decoded string contains only Unicode scalar values. A receiver rejects an unpaired UTF-16 surrogate escape rather than exposing implementation- dependent string behavior.
3. Scalar Mapping¶
Initial protocol values use these JSON representations:
Logical value |
JSON representation |
|---|---|
Protocol version |
integer from |
Message kind |
exact string from the finite kind set |
Request, Operation, Context, and Block IDs |
non-empty string |
Lifecycle |
|
Response outcome |
exact string defined by that response schema |
Error code |
exact string from the version’s |
Content type |
exact string identifier; baseline is |
Extend fragment |
non-empty string containing |
ReplaceSuffix retained-prefix count |
integer from |
ReplaceSuffix replacement |
string containing |
Human diagnostic |
string |
The bounded version range is exactly representable by common integer and JSON implementations and leaves version comparison independent of floating-point or arbitrary-precision behavior.
The ReplaceSuffix count limit is the largest integer represented exactly by common JSON number implementations. It is a serialization ceiling, not a promise that a terminal accepts Blocks of that size; ordinary resource limits still apply.
IDs are compared as exact decoded strings. Implementations do not perform Unicode normalization, case folding, numeric parsing, or interpretation of an ID’s internal form. A decimal counter or UUID may be used by its owner, but that structure has no protocol meaning.
The initial envelope and baseline message bodies use no JSON booleans or
null. Their only numeric values are version and ReplaceSuffix’s retain.
An optional field is omitted when absent; it is not represented by null.
4. Structures and Content¶
Logical records become JSON objects and logical arrays become JSON arrays.
The optional_content_types value is an array of unique Content Type strings.
Its order has no semantic meaning.
A ContentSnapshot serializes as:
{
"type": "text/plain",
"data": "complete block text"
}
For text/plain, data is a JSON string containing the complete logical text
snapshot. JSON escaping represents characters in transit but does not change
the decoded content. In particular, escape-looking content is data and cannot
become a terminal control sequence.
An optional content type defines the JSON type and closed schema of its own
data value. If it permits JSON numbers, it must also define an interoperable
range and precision. A receiver does not accept arbitrary JSON merely because
the outer ContentSnapshot is structurally valid.
A complete serialized Update may therefore be written as:
{
"version": 1,
"kind": "block.update",
"operation_id": "42",
"context_id": "ctx-1",
"body": {
"block_id": "thinking-1",
"content": {
"type": "text/plain",
"data": "complete replacement text"
}
}
}
A serialized Extend names the exact prior content Operation and carries only the non-empty text fragment:
{
"version": 1,
"kind": "block.extend",
"operation_id": "43",
"context_id": "ctx-1",
"body": {
"block_id": "thinking-1",
"base_operation_id": "42",
"fragment": " additional text"
}
}
base_operation_id follows the same non-empty string mapping as every other
Operation ID. An empty fragment violates the closed block.extend body
schema and produces invalid_message when correlation identity is reliable.
A serialized ReplaceSuffix carries a safe integer boundary and replacement text that may be empty:
{
"version": 1,
"kind": "block.replace_suffix",
"operation_id": "44",
"context_id": "ctx-1",
"body": {
"block_id": "thinking-1",
"base_operation_id": "43",
"retain": 12,
"replacement": "revised ending"
}
}
A negative, fractional, or greater-than-9007199254740991 retain value
violates the closed body schema and produces invalid_message when correlation
identity is reliable. A structurally valid value that is not below the current
text’s scalar-value length instead produces invalid_content_boundary.
5. Field Names and Closed Schemas¶
JSON member names exactly match the snake-case field names in the concrete message schemas. Names and string enums are case-sensitive. Aliases, abbreviations, alternate casing, and implementation-specific members are not accepted.
Missing required members, unexpected members, forbidden envelope members,
wrong JSON types, and invalid tagged alternatives make the complete Message
invalid. An invalid TUI-to-terminal control request or Block Operation with
trustworthy correlation identity reports invalid_message; the receiver does
not remove an invalid member and execute the remainder. An invalid
terminal-to-TUI Message does not cause a reverse error response, and a
protocol.error never receives a protocol response.
6. Parsing Failure and Correlation¶
The receiver validates a complete framed payload in this order:
Decode strict UTF-8 and parse the single JSON object, rejecting duplicate member names and invalid Unicode scalar values.
Validate the common envelope for a recognized version and message kind.
Validate the selected closed body schema.
Evaluate the Message’s semantic preconditions.
Invalid UTF-8, invalid JSON, duplicate member names, or a non-object top-level value provides no trustworthy logical identity. The receiver discards that framed payload and emits no correlated protocol response. Framing recovery then continues at the next valid frame boundary.
Once the request or Operation identity required by a recognized
TUI-to-terminal schema has been validated, later structural and semantic
failures use that message kind’s correlated reporting path and ErrorCode
rules. A malformed terminal-to-TUI response or protocol.error is discarded
and may be diagnosed locally; it does not trigger another protocol Message.
7. Logical Equality and Retransmission¶
No canonical JSON byte representation is required. Senders may choose member order, insignificant whitespace, and valid character escape forms.
When retry rules require the receiver to determine whether a request ID refers to the same logical request, it compares the decoded logical Message, not its original JSON bytes. Differences in member order, whitespace, or equivalent JSON string escaping do not create a different request.
8. Separation from Framing and Carrier¶
JSON escaping protects JSON syntax only. It does not protect a payload from a terminal carrier’s delimiters or control bytes. The OSC framing layer carries the complete UTF-8 payload without truncation, delimiter injection, or accidental terminal execution.
Serialization adds no compression. Any future compression belongs to an explicitly defined and negotiated framing layer and must preserve the same decoded logical Message.
Open Design Choices¶
Maximum JSON nesting depth, string length, and identifier length within the framing layer’s complete-Message limit.
JSON
dataschemas for future optional content types.
Baseline display processing is defined by Plain Text Content, not JSON serialization. Decoding preserves the original scalar sequence.