JSON Structure: Semantic and Reference-System Annotations
draft-vasters-json-structure-sem-ann-00
This document is an Internet-Draft (I-D).
Anyone may submit an I-D to the IETF.
This I-D is not endorsed by the IETF and has no formal standing in the
IETF standards process.
| Document | Type | Active Internet-Draft (individual) | |
|---|---|---|---|
| Author | Clemens Vasters | ||
| Last updated | 2026-08-06 | ||
| RFC stream | (None) | ||
| Intended RFC status | (None) | ||
| Formats | |||
| Stream | Stream state | (No stream defined) | |
| Consensus boilerplate | Unknown | ||
| RFC Editor Note | (None) | ||
| IESG | IESG state | I-D Exists | |
| Telechat date | (None) | ||
| Responsible AD | (None) | ||
| Send notices to | (None) |
draft-vasters-json-structure-sem-ann-00
Network Working Group C. Vasters
Internet-Draft Microsoft Corporation
Intended status: Standards Track 6 August 2026
Expires: 7 February 2027
JSON Structure: Semantic and Reference-System Annotations
draft-vasters-json-structure-sem-ann-00
Abstract
Data types describe representation, but they do not explain the
semantic, temporal, spatial, and operational characteristics needed
to interpret and compare data. This document defines optional JSON
Structure annotations that bind schema nodes to terms in external
vocabularies; annotations for observation results, observed
properties, features of interest, procedures, time semantics,
quality, derivation, and cadence; annotations for spatial referencing
by coordinates, by vector and tensor reference frames, by
transformations between frames, and along linear elements; and
annotations for color spaces, audio channel layouts, spectral bands,
code lists, and measurement conditioning.
The annotations make an incompatibility between two data sets
detectable by machine; they do not resolve one. They are optional,
and their absence does not make a schema invalid.
About This Document
This note is to be removed before publishing as an RFC.
The latest revision of this draft can be found at https://json-
structure.github.io/semantic-annotations/draft-vasters-json-
structure-sem-ann.html. Status information for this document may be
found at https://datatracker.ietf.org/doc/draft-vasters-json-
structure-sem-ann/.
Source for this draft and an issue tracker can be found at
https://github.com/json-structure/semantic-annotations.
Status of This Memo
This Internet-Draft is submitted in full conformance with the
provisions of BCP 78 and BCP 79.
Vasters Expires 7 February 2027 [Page 1]
Internet-Draft JSON Structure Semantic Annotations August 2026
Internet-Drafts are working documents of the Internet Engineering
Task Force (IETF). Note that other groups may also distribute
working documents as Internet-Drafts. The list of current Internet-
Drafts is at https://datatracker.ietf.org/drafts/current/.
Internet-Drafts are draft documents valid for a maximum of six months
and may be updated, replaced, or obsoleted by other documents at any
time. It is inappropriate to use Internet-Drafts as reference
material or to cite them other than as "work in progress."
This Internet-Draft will expire on 7 February 2027.
Copyright Notice
Copyright (c) 2026 IETF Trust and the persons identified as the
document authors. All rights reserved.
This document is subject to BCP 78 and the IETF Trust's Legal
Provisions Relating to IETF Documents (https://trustee.ietf.org/
license-info) in effect on the date of publication of this document.
Please review these documents carefully, as they describe your rights
and restrictions with respect to this document. Code Components
extracted from this document must include Revised BSD License text as
described in Section 4.e of the Trust Legal Provisions and are
provided without warranty as described in the Revised BSD License.
Table of Contents
1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 5
1.1. Semantic Binding and External Definitions . . . . . . . . 7
1.2. Observable and Observed Property Concepts . . . . . . . . 8
2. Conventions . . . . . . . . . . . . . . . . . . . . . . . . . 8
3. Annotation Model . . . . . . . . . . . . . . . . . . . . . . 9
4. Vocabulary Annotations . . . . . . . . . . . . . . . . . . . 13
4.1. The concepts Keyword . . . . . . . . . . . . . . . . . . 13
4.1.1. The reference Property . . . . . . . . . . . . . . . 13
4.1.2. The kind Property . . . . . . . . . . . . . . . . . . 13
4.1.3. Type Compatibility . . . . . . . . . . . . . . . . . 14
4.1.4. Relationship to the Annotation Model . . . . . . . . 15
4.1.5. Relationship to observedProperty . . . . . . . . . . 15
5. Observation Annotations . . . . . . . . . . . . . . . . . . . 17
5.1. The observedProperty Keyword . . . . . . . . . . . . . . 17
5.1.1. The reference Property . . . . . . . . . . . . . . . 17
5.1.2. The kind Property . . . . . . . . . . . . . . . . . . 17
5.1.3. Attachment and Scope . . . . . . . . . . . . . . . . 18
5.2. Semantic Mappings and Result Hints . . . . . . . . . . . 20
5.3. The semanticRole Keyword . . . . . . . . . . . . . . . . 20
5.3.1. Observation Result Concern . . . . . . . . . . . . . 21
Vasters Expires 7 February 2027 [Page 2]
Internet-Draft JSON Structure Semantic Annotations August 2026
5.3.2. Feature and Procedure Concern . . . . . . . . . . . . 22
5.3.3. Temporal Concern (Observation Time) . . . . . . . . . 26
5.3.4. Temporal Concern (Flattened Period Boundaries) . . . 28
5.3.5. Temporal Concern (Operational Event Time) . . . . . . 30
5.3.6. Status Concern . . . . . . . . . . . . . . . . . . . 34
5.4. The derivation Keyword . . . . . . . . . . . . . . . . . 35
5.5. The statistic Keyword . . . . . . . . . . . . . . . . . . 37
6. Coded Value Annotations . . . . . . . . . . . . . . . . . . . 43
6.1. The codedValues Keyword . . . . . . . . . . . . . . . . . 44
6.1.1. The reference and kind Properties . . . . . . . . . . 44
6.1.2. Example . . . . . . . . . . . . . . . . . . . . . . . 46
7. Measurement Conditioning Annotations . . . . . . . . . . . . 46
7.1. The measurementConditioning Keyword . . . . . . . . . . . 46
7.1.1. The weighting Property . . . . . . . . . . . . . . . 47
7.1.2. The timeWeighting Property . . . . . . . . . . . . . 47
7.1.3. The levelReference Property . . . . . . . . . . . . . 48
7.1.4. Example . . . . . . . . . . . . . . . . . . . . . . . 48
8. Reference System Meta-Types . . . . . . . . . . . . . . . . . 49
8.1. The referenceRole Keyword . . . . . . . . . . . . . . . . 49
9. Temporal Reference Annotations . . . . . . . . . . . . . . . 50
9.1. The phenomenonTimeRelation Keyword . . . . . . . . . . . 51
9.2. The supportPeriod Keyword . . . . . . . . . . . . . . . . 53
9.2.1. The length Property . . . . . . . . . . . . . . . . . 53
9.2.2. The anchor Property . . . . . . . . . . . . . . . . . 53
9.3. The temporalReferenceSystem Keyword . . . . . . . . . . . 56
9.3.1. The reference Property . . . . . . . . . . . . . . . 56
9.3.2. The kind Property . . . . . . . . . . . . . . . . . . 56
9.3.3. The position Property . . . . . . . . . . . . . . . . 57
9.3.4. The sortOrder Property . . . . . . . . . . . . . . . 58
9.3.5. Type Compatibility . . . . . . . . . . . . . . . . . 58
9.4. The cadence Keyword . . . . . . . . . . . . . . . . . . . 61
9.4.1. The kind Property . . . . . . . . . . . . . . . . . . 62
9.4.2. The period Property . . . . . . . . . . . . . . . . . 62
10. Spatial Reference Annotations . . . . . . . . . . . . . . . . 66
10.1. The coordinateReferenceSystem Keyword . . . . . . . . . 66
10.1.1. The reference Property . . . . . . . . . . . . . . . 66
10.1.2. The kind Property . . . . . . . . . . . . . . . . . 67
10.1.3. The coordinates Property . . . . . . . . . . . . . . 67
10.1.4. Vertical and Compound Systems . . . . . . . . . . . 70
10.2. The vectorReferenceFrames Keyword . . . . . . . . . . . 72
10.2.1. The reference and kind Properties . . . . . . . . . 73
10.2.2. The components Property . . . . . . . . . . . . . . 73
10.2.3. The variance Property . . . . . . . . . . . . . . . 74
10.2.4. Multiple Frames and Shared Components . . . . . . . 75
10.3. The tensorReferenceFrames Keyword . . . . . . . . . . . 78
10.3.1. The frames Property . . . . . . . . . . . . . . . . 79
10.3.2. The components Property . . . . . . . . . . . . . . 81
10.4. The frameTransforms Keyword . . . . . . . . . . . . . . 84
Vasters Expires 7 February 2027 [Page 3]
Internet-Draft JSON Structure Semantic Annotations August 2026
10.4.1. The Conventions This Document Fixes . . . . . . . . 85
10.4.2. The from and to Properties . . . . . . . . . . . . . 86
10.4.3. The encoding Property . . . . . . . . . . . . . . . 86
10.4.4. The components Property . . . . . . . . . . . . . . 88
10.4.5. The rotationSequence Property . . . . . . . . . . . 92
10.4.6. The translation Property . . . . . . . . . . . . . . 94
10.5. The linearReferenceSystem Keyword . . . . . . . . . . . 97
10.5.1. The reference Property . . . . . . . . . . . . . . . 97
10.5.2. The kind Property . . . . . . . . . . . . . . . . . 98
10.5.3. The linearElement Property . . . . . . . . . . . . . 99
10.5.4. The measure Property . . . . . . . . . . . . . . . . 99
10.5.5. The measureEnd Property . . . . . . . . . . . . . . 99
10.5.6. The direction Property . . . . . . . . . . . . . . . 99
11. Colorimetric Reference Annotations . . . . . . . . . . . . . 101
11.1. The colorSpaces Keyword . . . . . . . . . . . . . . . . 101
11.1.1. The reference and kind Properties . . . . . . . . . 102
11.1.2. The codePoints Property . . . . . . . . . . . . . . 104
11.1.3. The channels Property . . . . . . . . . . . . . . . 105
11.1.4. The packing Property . . . . . . . . . . . . . . . . 105
11.1.5. The alpha and alphaMode Properties . . . . . . . . . 107
11.1.6. The transfer Property . . . . . . . . . . . . . . . 108
11.1.7. The illuminant and observer Properties . . . . . . . 109
11.1.8. Example . . . . . . . . . . . . . . . . . . . . . . 110
12. Signal Channel Annotations . . . . . . . . . . . . . . . . . 112
12.1. The audioChannels Keyword . . . . . . . . . . . . . . . 112
12.1.1. The reference and kind Properties . . . . . . . . . 113
12.1.2. The channels Property . . . . . . . . . . . . . . . 113
12.1.3. The levelReference Property . . . . . . . . . . . . 114
12.1.4. The encoding Property . . . . . . . . . . . . . . . 114
12.1.5. Example . . . . . . . . . . . . . . . . . . . . . . 116
12.2. The spectralBands Keyword . . . . . . . . . . . . . . . 116
12.2.1. The reference and kind Properties . . . . . . . . . 117
12.2.2. The bands Property . . . . . . . . . . . . . . . . . 118
12.2.3. The calibration Property . . . . . . . . . . . . . . 118
12.2.4. Example . . . . . . . . . . . . . . . . . . . . . . 119
13. Conformance . . . . . . . . . . . . . . . . . . . . . . . . . 120
13.1. Check Outcomes . . . . . . . . . . . . . . . . . . . . . 120
13.2. Schema Conformance . . . . . . . . . . . . . . . . . . . 120
13.3. Processing Conformance . . . . . . . . . . . . . . . . . 121
13.4. Inheritance and Imports . . . . . . . . . . . . . . . . 123
14. Extension Meta-Schema . . . . . . . . . . . . . . . . . . . . 123
15. Security Considerations . . . . . . . . . . . . . . . . . . . 124
15.1. Privacy Considerations . . . . . . . . . . . . . . . . . 125
16. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 125
17. References . . . . . . . . . . . . . . . . . . . . . . . . . 125
17.1. Normative References . . . . . . . . . . . . . . . . . . 125
17.2. Informative References . . . . . . . . . . . . . . . . . 127
Appendix A. Reference URIs (Informative) . . . . . . . . . . . . 133
Vasters Expires 7 February 2027 [Page 4]
Internet-Draft JSON Structure Semantic Annotations August 2026
A.1. Vocabularies . . . . . . . . . . . . . . . . . . . . . . 133
A.2. Temporal Reference Systems . . . . . . . . . . . . . . . 133
A.3. Coordinate Reference Systems . . . . . . . . . . . . . . 135
A.4. Vector Reference Frames . . . . . . . . . . . . . . . . . 135
A.5. Linear Reference Systems . . . . . . . . . . . . . . . . 136
A.6. Code Lists . . . . . . . . . . . . . . . . . . . . . . . 136
Change Log . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . . . 137
Author's Address . . . . . . . . . . . . . . . . . . . . . . . . 138
1. Introduction
A schema states how a value is written. It gives a type, and with
JSON Structure Units [JSTRUCT-UNITS] it gives a unit, so that a
reader knows a member holds a number of metres. It does not state
what the number measures, what the metres are measured from, or when
the measurement applies. Two schemas can agree on double and on m
and still describe water level above a tide-gauge datum and height
above an ellipsoid, which are not the same quantity and must not be
compared. That difference is usually recorded in prose
documentation, inferred from a member name, or known only to the
people who built the system.
This document is an extension to JSON Structure Core [JSTRUCT-CORE]
that records it in the schema, by annotation, without changing what
the schema validates. Its keywords let a schema author:
* bind a type or member to a term in a published vocabulary, so that
two systems naming a thing differently can establish that they
mean the same thing;
* declare what a record observes and which member carries the
result, as distinct from the property observed, the feature it
belongs to, the procedure that produced it, and the time it
applies to;
* name the reference system a value is expressed against, whether a
temporal regime, a coordinate reference system, a vector or tensor
reference frame, a transformation from one frame to another, or a
linear reference system, so that a position, a direction, or an
orientation can be interpreted and two of them compared; and
* resolve the members that together carry one compound value onto
the axes, channels, or bands that give them meaning, whether those
of a color space, an audio channel layout, or a set of spectral
bands.
Vasters Expires 7 February 2027 [Page 5]
Internet-Draft JSON Structure Semantic Annotations August 2026
The same concern applies to a value that stands alone. One keyword
binds a coded value to the register that assigns the code its
meaning, so that a number or a short string can be resolved rather
than guessed at from a member name. Another records the frequency
weighting, time weighting, and level reference that a conditioned
measurement already carries, so that a sound level measured under one
weighting is not silently compared with one measured under another.
Most of these are bindings to a definition maintained elsewhere.
This document defines no vocabulary, no reference system, no color
space, no channel layout, and no code list of its own. Established
bodies publish them, and an annotation refers to one. What is
defined here is the form of that reference, the roles a schema may
assign to its own members, and the rules by which a processor can
check that the two agree.
The roles are the one place where that account needs qualifying.
semanticRole and derivation do carry a vocabulary of observation
concepts, and this document does not pretend otherwise. What it
declines to be is a normative encoding of the observation model of
[ISO19156]. It defines no observation as a type to instantiate, no
classes for procedures or features, and no relationships among
observation entities, and it requires no record to be shaped like an
observation. The roles describe what the members of a record already
are, over a structure someone else fixed. A record does not become
an observation by carrying them, a schema that carries none is not
deficient for that reason, and a processor does not reconstruct an
observation entity from the roles it finds (Section 13.3).
Nor does this document define analytical procedures. Several
keywords name an operation, and naming one is not specifying it. A
schema that declares a value an hourly mean records an operation that
has already been performed; it does not state what a mean computes,
how gaps in the set were treated, whether the window was inclusive of
its bounds, or whether a consumer may recompute the value. The
annotations describe what was done, and a processor does not read an
instruction out of them (Section 13.3).
Nor does it define a lineage model, although several keywords carry
lineage facts: derivation says how a value was produced,
observingProcedure identifies what produced it, and ingestionTime
says when a system received it. [PROV-O] gives entities, activities,
and agents identities and relates them by derivation and attribution.
What is here is flat and confined to one record, with no identity for
the act that produced a value and no way to chain a value to the
value it came from. The two do not conflict and a record can carry
both; the concepts example maps a publication instant onto
prov:generatedAtTime (Section 4.1).
Vasters Expires 7 February 2027 [Page 6]
Internet-Draft JSON Structure Semantic Annotations August 2026
The keywords defined here are chosen by one test. A quality of a
value earns a keyword when a consumer must know it to decide whether
two values may be combined or compared, and when it holds for the
type rather than varying from one instance to the next. Axis order,
frequency weighting, and the register a code is drawn from meet that
test: get one of them wrong and an arithmetic result is wrong while
every value still validates. Licensing, retention, and endpoint
addressing do not meet it, because they do not change what may be
computed from a value. A per-observation calibration record does not
meet it, because it varies from one record to the next and belongs in
the payload rather than in the schema. Geometry, provenance, and
unit algebra do not meet it, because each is a model in its own right
that another specification defines; this document cites those rather
than restating them.
The annotations are optional and additive. A processor that does not
implement them reads the schema exactly as JSON Structure Core
defines it. This document defines no conversion, and a processor
that cannot resolve a referenced definition reports the check as
indeterminate rather than assuming agreement. Correctly declining to
combine two values is the outcome these annotations enable;
transforming them so that they can be combined remains the work of a
tool that holds the authoritative definitions.
1.1. Semantic Binding and External Definitions
Most keywords defined here share one shape. Each is an object
carrying a reference property that identifies a definition and a kind
property that names the model the definition belongs to. This lets a
reader know how to interpret it and a processor know what can be
checked. concepts, observedProperty, temporalReferenceSystem,
coordinateReferenceSystem, linearReferenceSystem, codedValues, the
entries of vectorReferenceFrames, colorSpaces, audioChannels, and
spectralBands, and the frames named by tensorReferenceFrames and
frameTransforms all follow this shape.
A definition is ordinarily maintained outside the schema, and
reference is then an absolute URI [RFC3986]. Every one of these
keywords except concepts and observedProperty also admits a
definition held in the schema itself, carried by a shareable type
that Section 8 calls a meta-type; kind is then type and reference is
a type reference { "$ref": <JSON Pointer> } to that type. The kind
determines which form applies, and each keyword states the rule for
its own values.
A kind names a definition model and not the format of the resource
that carries it. The enumerations are open so that an author whose
model is not already named can name it.
Vasters Expires 7 February 2027 [Page 7]
Internet-Draft JSON Structure Semantic Annotations August 2026
The annotations bind terms; they do not express statements, node
identity, or entailment, and this document defines no prefix
mechanism and no compact URI form.
A value is read against one temporal or coordinate reference system,
quantifies one phenomenon, and draws its code from one register, so
those keywords, observedProperty, and codedValues each take a single
binding. Vocabularies overlap by design, and the same notion is
deliberately given a term in several of them, so concepts takes a
list. The keywords that resolve components onto axes, channels, or
bands take a list for a different reason: one record can carry
several such quantities at once, and one set of numbers can be
published in more than one frame or more than one color space at
once.
measurementConditioning stands apart from this shape. It identifies
no external definition, because what it records is not a system a
value is read against but a treatment the value has already
undergone, and it states that treatment directly.
1.2. Observable and Observed Property Concepts
Observation is one application of the general model in Section 1.1.
An _observable property definition_ is the externally governed
concept, such as water level or bridge vibration, and this document
defines no format for one. An _observed property declaration_ is the
observedProperty annotation that binds one record shape to one such
definition.
An observation act is one concrete execution of an observing
procedure for one declared observed property and feature context,
producing one result value and optionally its qualifiers.
2. Conventions
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
"SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and
"OPTIONAL" in this document are to be interpreted as described in
BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all
capitals, as shown here.
Some examples in this document contain lines that exceed the maximum
line length permitted in an RFC. Those examples use the single
backslash line wrapping strategy of [RFC8792] and carry the header
that strategy defines. A line ending in a backslash is continued by
the first non-space character of the following line; the backslash,
the line break, and the leading whitespace are removed to recover the
original text.
Vasters Expires 7 February 2027 [Page 8]
Internet-Draft JSON Structure Semantic Annotations August 2026
3. Annotation Model
concepts MAY occur on a type definition and on a property, collection
item, map value, or choice member schema, subject to Section 4.
semanticRole, derivation, temporalReferenceSystem, and cadence MAY
occur directly on a property, collection item, map value, or choice
member schema, subject to Section 5. phenomenonTimeRelation and
supportPeriod MAY occur on a direct property. statistic MAY occur
wherever derivation occurs, subject to Section 5.5.
temporalReferenceSystem MAY also occur on an object or tuple that
defines a temporal type, and binds an existing member of it.
observedProperty MAY occur on an object or tuple intended to describe
an observation record, and on a member schema of one that carries a
result, subject to Section 5.1. coordinateReferenceSystem,
vectorReferenceFrames, tensorReferenceFrames, frameTransforms,
linearReferenceSystem, colorSpaces, audioChannels, and spectralBands
MAY occur on an object or tuple and bind existing properties.
codedValues and measurementConditioning MAY occur on a property,
collection item, map value, or choice member schema, subject to their
sections. referenceRole MAY occur on a member of a meta-type, subject
to Section 8.
All keywords defined here are direct peer keywords, and no wrapper is
implied. Every annotation is OPTIONAL, and a schema can use any
subset, including none. Conformance constrains only annotations that
are present; it never requires another annotation or an annotated
property to exist.
Several keywords bind members of the annotated type by name. Such a
name is the name of the property as declared in the schema, and it is
resolved against the effective definition of the annotated type,
which includes members contributed by $extends and members of an
imported or shadowing definition [JSTRUCT-IMPORT]. A name that does
not resolve to a direct member of that effective definition is
invalid. An alternate, localized, or otherwise serialization-facing
name assigned to a member by another extension, such as JSON
Structure Alternate Names [JSTRUCT-ALTNAMES], changes how the member
appears in an instance document and does not change the identity the
annotation binds; a processor MUST NOT resolve a member name stated
in an annotation against such a name, and MUST NOT treat the presence
of one as altering the mapping.
Every reference value that is a URI SHOULD be resolvable, and
dereferencing it SHOULD yield a definition of the identified term or
system. A processor is not required to dereference a reference, and
an unresolved reference is indeterminate rather than incorrect.
Vasters Expires 7 February 2027 [Page 9]
Internet-Draft JSON Structure Semantic Annotations August 2026
A reference identifies whatever its URI identifies, revision
included, and this document defines no version, epoch, or as-of
member to stand beside it. A body that revises definitions and means
them to stay citable puts the revision in the identifier, which is
what the naming policy behind the identifiers used throughout this
document provides for: a definition is named
/def/{objectType}/{authority}/{version}/{code} [OGC-NAMES], so the 0
in http://www.opengis.net/def/crs/EPSG/0/4326 occupies a version
position that a schema needing one edition rather than another fills
in. A schema pins an edition by writing the identifier the publisher
supplies for it.
A separate member would state in a second place what the URI already
carries, and no processor could reconcile the two without resolving
the reference, which none is required to do. Where a publisher
revises without giving each revision an identifier, a schema SHOULD
record that fact in description, which informs a reader without
inviting a processor to act on it.
The enumerations of this document are of two sorts, and one rule
divides them. An enumeration is closed where its values select a
behavior that this document itself defines, so that a value outside
it would establish nothing for any processor. An enumeration is open
where its values name a model, register, or definition that another
body maintains, because this document cannot enumerate what others
publish and a value it has not heard of may still be one that a
reader knows.
Closed are semanticRole, derivation, statistic in both of its forms,
phenomenonTimeRelation, referenceRole, sortOrder, the kind of
cadence, the anchor of supportPeriod, the variance of
vectorReferenceFrames and tensorReferenceFrames, the symmetry of
tensorReferenceFrames, the encoding and rotationSequence of
frameTransforms, and the alphaMode and transfer of colorSpaces. A
value outside a closed enumeration is invalid.
Open are the kind of every reference-style keyword, the weighting and
timeWeighting of measurementConditioning, the levelReference of both
measurementConditioning and audioChannels, the calibration of
spectralBands, and the encoding of audioChannels. A value outside an
open enumeration is valid; a processor MUST preserve it and MUST NOT
reject a schema for carrying it.
Closure states where a value's meaning comes from, and is not a claim
that a list is finished. A later version of this document may add
values to a closed enumeration, and the versioned meta-schema URI a
schema names is what tells a processor which set is in force
(Section 14).
Vasters Expires 7 February 2027 [Page 10]
Internet-Draft JSON Structure Semantic Annotations August 2026
A value defined here is one a processor can act on, and this document
states what each establishes. A value not defined here establishes
nothing, and a processor MUST NOT infer a constraint from it. This
document defines no registry of further values and no mechanism by
which a private value acquires meaning for a processor that does not
already know it.
Because the open enumerations are open, two authors may choose one
token for two unrelated things. kind classifies and reference
identifies, and that division bounds the consequence. A processor
MUST NOT treat a kind value as establishing the identity of a
definition, and MUST NOT conclude from two schemas carrying equal
kind values that they draw on the same register, model, or
definition. Where kind agrees and reference does not, the references
govern. A processor meeting a kind it does not recognize reports the
check indeterminate (Section 13.1).
That bounds a collision rather than preventing one. A registry of
kind values is the remedy; a future revision of this document is
expected to establish one, and none exists at the time of writing.
Until one does, a kind value outside those defined here means what it
means only to a processor that already knows it. A schema SHOULD use
a value defined here where one fits, and SHOULD NOT coin a broad
token such as sensor or registry for a private arrangement, since the
broadest tokens are the ones most likely to be coined twice.
+===========================+=====================================+
| Keyword | Meaning |
+===========================+=====================================+
| concepts | Terms in external vocabularies that |
| | the annotated node corresponds to. |
+---------------------------+-------------------------------------+
| semanticRole | Function of a result, temporal, |
| | quality, status, or operational |
| | value. |
+---------------------------+-------------------------------------+
| observedProperty | Reference to an observable-property |
| | definition. |
+---------------------------+-------------------------------------+
| phenomenonTimeRelation | Refinement of how a result relates |
| | to phenomenonTime. |
+---------------------------+-------------------------------------+
| supportPeriod | Length of the phenomenon-time |
| | period a result characterizes, and |
| | the position anchoring it. |
+---------------------------+-------------------------------------+
| derivation | Category describing how a result |
| | value was produced. |
Vasters Expires 7 February 2027 [Page 11]
Internet-Draft JSON Structure Semantic Annotations August 2026
+---------------------------+-------------------------------------+
| statistic | Summary function that produced a |
| | result from a set of values. |
+---------------------------+-------------------------------------+
| temporalReferenceSystem | Binding from a temporal-position |
| | encoding to its reference |
| | definition. |
+---------------------------+-------------------------------------+
| cadence | Expected pattern of successive |
| | temporal positions. |
+---------------------------+-------------------------------------+
| coordinateReferenceSystem | CRS and ordered properties forming |
| | a coordinate. |
+---------------------------+-------------------------------------+
| vectorReferenceFrames | Frames and ordered properties |
| | forming the components of vector |
| | quantities. |
+---------------------------+-------------------------------------+
| tensorReferenceFrames | Frames and indexed properties |
| | forming the components of tensor |
| | quantities. |
+---------------------------+-------------------------------------+
| frameTransforms | Frames and properties forming a |
| | transformation from one frame to |
| | another. |
+---------------------------+-------------------------------------+
| linearReferenceSystem | LRS and properties forming a |
| | location along a linear element. |
+---------------------------+-------------------------------------+
| colorSpaces | Color spaces and properties forming |
| | the channels of color values. |
+---------------------------+-------------------------------------+
| referenceRole | Function of a member within a |
| | reference-system meta-type. |
+---------------------------+-------------------------------------+
| audioChannels | Audio channel layout, level |
| | reference, and encoding for channel |
| | values. |
+---------------------------+-------------------------------------+
| spectralBands | Spectral bands and ordered |
| | properties forming the bands of a |
| | multiband value. |
+---------------------------+-------------------------------------+
| codedValues | Binding from a coded property to an |
| | external code list. |
+---------------------------+-------------------------------------+
| measurementConditioning | Frequency or time weighting and |
| | level reference a scalar |
Vasters Expires 7 February 2027 [Page 12]
Internet-Draft JSON Structure Semantic Annotations August 2026
| | measurement carries. |
+---------------------------+-------------------------------------+
Table 1
Omission means undeclared unless stated otherwise. It never implies
compatible, successful, or acceptable data.
4. Vocabulary Annotations
4.1. The concepts Keyword
The concepts keyword binds the annotated node to terms defined by
external vocabularies, following the model in Section 1.1. In this
document a concept is any term that a vocabulary defines, including a
class, a property, or a SKOS concept [SKOS]. The skos-concept kind
names one such term type and places no constraint on the others.
When present, concepts MUST be a non-empty array of objects. Each
object MUST have a REQUIRED reference string and a REQUIRED kind
string. No other properties are permitted.
The array is unordered and no entry is primary. Every entry holds
simultaneously: the annotated node corresponds to all of the terms
listed, and a reader does not select among them. Two entries MUST
NOT carry the same reference.
4.1.1. The reference Property
reference MUST be an absolute URI [RFC3986] that identifies one term.
The URI is the identifier that the vocabulary assigns to the term.
This document defines no prefix mechanism, no compact form, and no
resolution protocol.
4.1.2. The kind Property
kind classifies which definition model the URI identifies. It is an
open enumeration. The following values are defined:
Vasters Expires 7 February 2027 [Page 13]
Internet-Draft JSON Structure Semantic Annotations August 2026
+=======================+=====================================+
| Value | Referenced definition |
+=======================+=====================================+
| rdfs-class | A class in RDF Schema [RDF-SCHEMA]. |
+-----------------------+-------------------------------------+
| rdf-property | An RDF property [RDF-CONCEPTS]. |
+-----------------------+-------------------------------------+
| owl-class | A class in OWL 2 [OWL2]. |
+-----------------------+-------------------------------------+
| owl-object-property | An OWL 2 object property. |
+-----------------------+-------------------------------------+
| owl-datatype-property | An OWL 2 datatype property. |
+-----------------------+-------------------------------------+
| skos-concept | A concept in a SKOS concept scheme |
| | [SKOS]. |
+-----------------------+-------------------------------------+
| dcterms-property | A property in DCMI Metadata Terms |
| | [DCTERMS]. |
+-----------------------+-------------------------------------+
Table 2
Other values MAY identify further definition models. Appendix A.1
lists namespace URIs for the vocabularies named above.
4.1.3. Type Compatibility
A kind denotes either a class or a property, and the two attach to
different schema nodes:
* rdfs-class and owl-class denote a class, and the annotation MUST
occur on a type definition.
* rdf-property, owl-object-property, owl-datatype-property, and
dcterms-property denote a property, and the annotation MUST occur
on a property, collection item, map value, or choice member
schema.
* skos-concept denotes neither, and the annotation MAY occur on
either.
All entries of one concepts array MUST agree. An array MUST NOT
combine an entry whose kind denotes a class with an entry whose kind
denotes a property. A kind outside the values defined above
establishes no constraint, and a processor MUST NOT infer one.
Vasters Expires 7 February 2027 [Page 14]
Internet-Draft JSON Structure Semantic Annotations August 2026
4.1.4. Relationship to the Annotation Model
The keywords defined in this document already state the part a node
plays. A concepts entry that names a term whose meaning is that same
part carries no information beyond the annotation it accompanies and
SHOULD be omitted.
A node that carries observedProperty is an observation record by
Section 3, and SHOULD NOT also be bound to a general observation
class. A member that carries semanticRole SHOULD NOT also be bound
to a vocabulary property whose meaning is that same role, such as a
term for the result of an observation beside observationValue, or a
term for the feature that an observation is about beside
featureOfInterest.
concepts is for meaning that the annotation model does not carry: the
domain class of a record, the catalogue or taxonomic term that a
member names, or a correspondence that a consumer needs in order to
join the data to another vocabulary. A redundant entry is not an
error, and a processor MUST NOT reject a document for carrying one.
4.1.5. Relationship to observedProperty
concepts states which external terms the annotated node corresponds
to. observedProperty states which phenomenon a record quantifies.
Where the term is an observable-property definition, observedProperty
carries it and concepts MUST NOT name it. The same URI MUST NOT
appear in both keywords on one node.
Correspondences between one observable-property definition and terms
in other vocabularies belong to the definition and are recorded once
there, as described in Section 5.2. They are not repeated as
concepts entries in every schema that cites the definition.
A binding is a statement about meaning and not about resolution. A
missing or unresolved term is indeterminate and MUST NOT be repaired
from property names, descriptions, labels, or samples.
Example:
Vasters Expires 7 February 2027 [Page 15]
Internet-Draft JSON Structure Semantic Annotations August 2026
{
"name": "TideGaugeReading",
"type": "object",
"description": "One water-level reading from a tide gauge.",
"concepts": [
{
"reference": "http://www.w3.org/ns/sosa/Observation",
"kind": "owl-class"
}
],
"observedProperty": {
"reference":
"https://vocab.nerc.ac.uk/collection/P01/current/ASLVZZ01/",
"kind": "nerc-p01"
},
"properties": {
"waterLevel": {
"type": "double",
"unit": "m",
"description": "Height of the water surface above datum.",
"examples": [2.41],
"semanticRole": "observationValue",
"concepts": [
{
"reference": "http://www.w3.org/ns/sosa/hasSimpleResult",
"kind": "rdf-property"
}
]
},
"issued": {
"type": "datetime",
"description": "Instant at which the reading was published.",
"examples": ["2026-03-11T08:15:00Z"],
"concepts": [
{
"reference": "http://purl.org/dc/terms/issued",
"kind": "dcterms-property"
},
{
"reference": "http://www.w3.org/ns/prov#generatedAtTime",
"kind": "rdf-property"
}
]
}
}
}
Vasters Expires 7 February 2027 [Page 16]
Internet-Draft JSON Structure Semantic Annotations August 2026
5. Observation Annotations
5.1. The observedProperty Keyword
The observedProperty keyword identifies the observable-property
definition associated with an observation record, or with one result
within it, as introduced in Section 1.2.
When present, observedProperty MUST be an object with a REQUIRED
reference string and a REQUIRED kind string. No other properties are
permitted.
5.1.1. The reference Property
reference MUST be an absolute URI [RFC3986] that identifies one
immutable observable-property definition. Version identity, when
used, is implied by the URI itself, and a materially different
concept MUST be identified by a different URI. The URI SHOULD deep-
link to one concrete definition entry in the selected vocabulary.
This document does not define a resolution protocol, URI layout,
storage model, or catalog serialization.
5.1.2. The kind Property
kind classifies which definition model the URI identifies. It is an
open enumeration, and a value identifies the vocabulary or catalog
type that publishes the definition.
Examples of catalog types include:
* cf-standard-name for URIs identifying entries from the CF Standard
Name Table, for example a URI identifying air_temperature;
* nerc-p01 for entries from the NERC Vocabulary Server Parameter
Usage Vocabulary (P01) identified by dereferenceable concept URIs.
An organization that publishes its own catalog names its own model.
The examples in this document use example-catalog where the cited
catalog is fictional.
Example:
Vasters Expires 7 February 2027 [Page 17]
Internet-Draft JSON Structure Semantic Annotations August 2026
{
"observedProperty": {
"reference":
"https://vocab.nerc.ac.uk/collection/P01/current/CTMPZZ01/",
"kind": "nerc-p01"
}
}
5.1.3. Attachment and Scope
observedProperty MAY occur on an object or tuple that describes an
observation record, and on a member schema of that object or tuple
that carries a result.
On a record it identifies the observable property of every result in
that record that does not carry one of its own. On a result member
it identifies the observable property of that result alone and takes
precedence over the record's.
Every annotation identifies exactly one observable property for the
node it is attached to. A missing or unresolved reference is
indeterminate and MUST NOT be repaired from labels, mappings, result
schemas, units, descriptions, property names, or samples.
The feature, procedure, and temporal roles of a record are shared by
every result in it. Where a record carries more than one result, a
resultQuality on the record qualifies all of them, and qualifying one
result on its own requires modelling that result as a nested object.
Example of a record with two results:
Vasters Expires 7 February 2027 [Page 18]
Internet-Draft JSON Structure Semantic Annotations August 2026
{
"name": "BuoySurfacePacket",
"type": "object",
"properties": {
"buoy_id": {
"type": "string",
"semanticRole": "featureOfInterest"
},
"measured_at": {
"type": "datetime",
"description": "Time both results occurred",
"examples": ["2026-07-27T12:00:00Z"],
"semanticRole": "phenomenonTime"
},
"sea_surface_temperature": {
"type": "double",
"unit": "Cel",
"examples": [18.4],
"semanticRole": "observationValue",
"observedProperty": {
"reference":
"https://vocab.nerc.ac.uk/collection/P01/current/CTMPZZ01/",
"kind": "nerc-p01"
}
},
"practical_salinity": {
"type": "double",
"unit": "1",
"examples": [35.1],
"semanticRole": "observationValue",
"observedProperty": {
"reference":
"https://vocab.nerc.ac.uk/collection/P01/current/PSLTZZ01/",
"kind": "nerc-p01"
}
}
},
"required": [
"buoy_id", "measured_at", "sea_surface_temperature",
"practical_salinity"
],
"additionalProperties": false
}
Vasters Expires 7 February 2027 [Page 19]
Internet-Draft JSON Structure Semantic Annotations August 2026
5.2. Semantic Mappings and Result Hints
An authority MAY publish semantic mappings from an observable-
property definition to other identified concepts, using relation
kinds such as exactMatch, closeMatch, broader, narrower, related, and
quantityKind. Mapping targets MUST be absolute URIs, and a mapping
SHOULD carry a review state such as proposed, reviewed, or rejected.
Only a reviewed exactMatch can provide evidence that two distinct
identifiers denote the same observable property. closeMatch,
hierarchy, relatedness, label similarity, and quantity-kind
classification do not establish equivalence, and no mapping alone
authorizes execution.
A quantityKind mapping can reference a QUDT QuantityKind [QUDT] as a
classification and compatibility hint. Other mappings can target CF
Standard Names, SOSA/SSN concepts, or agency vocabularies
[CF-STANDARD-NAMES] [SOSA-SSN].
An authority MAY identify an expected result schema. That schema and
any quantity-kind mapping are hints; the actual result schema and
JSON Structure Units annotations remain authoritative. An
observable-property definition MUST NOT override unit semantics or
duplicate authoritative dimensions, unit lists, conversion factors,
or conversion formulas.
5.3. The semanticRole Keyword
The semanticRole keyword identifies the observation or operational
function of an annotated value.
The value of semanticRole MUST be one of a closed set of permitted
values defined in this section. A semanticRole value is never a URI;
terms drawn from external vocabularies are carried by concepts
instead.
semanticRole is scalar; therefore each annotated schema element can
carry one semanticRole value.
One containing type MUST NOT declare two direct members with the same
value for any of phenomenonTime, resultTime, effectiveTime,
phenomenonTimeStart, phenomenonTimeEnd, effectiveTimeStart,
effectiveTimeEnd, ingestionTime, scheduledTime, actualTime, or
forecastIssueTime. Each of these roles identifies one position, and
every rule in this document that resolves such a role to a member
presumes one. A type declaring two leaves those rules unresolvable
rather than ambiguous.
Vasters Expires 7 February 2027 [Page 20]
Internet-Draft JSON Structure Semantic Annotations August 2026
The observation-result and feature roles carry no such restriction.
Repetition is meaningful for them, and the sections defining them
state what it projects.
5.3.1. Observation Result Concern
A record using the roles of this concern, together with the feature
and procedure roles defined below:
{
"name": "WaterLevelObservation",
"type": "object",
"observedProperty": {
"reference": "https://example.org/props/water-level/v1",
"kind": "example-catalog"
},
"properties": {
"station": {
"type": "string",
"examples": ["USGS-12149000"],
"semanticRole": "featureOfInterest"
},
"procedure": {
"type": "string",
"examples": ["Pressure transducer"],
"semanticRole": "observingProcedure"
},
"result": {
"type": "double",
"description": "Water level above datum",
"unit": "m",
"examples": [2.47],
"semanticRole": "observationValue"
},
"quality": {
"type": "string",
"description": "Quality classification for this result",
"examples": ["validated", "estimated"],
"semanticRole": "resultQuality"
}
},
"required": ["station", "procedure", "result", "quality"],
"additionalProperties": false
}
Vasters Expires 7 February 2027 [Page 21]
Internet-Draft JSON Structure Semantic Annotations August 2026
5.3.1.1. observationValue
A property carrying the result of an observation act.
An observationValue is the outcome of one observation act, not the
act itself. Each act is represented by one complete value in one
annotated property. Structured or composite results can be
represented with an object, tuple, or another compatible compound
type. Multiple observationValue properties in the same containing
type represent multiple results, not one combined act.
5.3.1.2. resultQuality
One result-quality value associated with the observation,
corresponding to ISO result semantics [ISO19156].
resultQuality qualifies the observationValue; it is not the result
value itself.
A single observation act can carry multiple quality qualifiers, and
each direct property with semanticRole: resultQuality projects one of
them.
The value schema or external vocabulary defines the quality scale.
This specification defines no threshold, ordering, confidence model,
or processing effect. Omission does not imply acceptable quality.
Procedure-level quality metadata describes the measuring process in
general and is distinct from resultQuality, which describes one
observation result.
5.3.2. Feature and Procedure Concern
A record using the roles of this concern:
Vasters Expires 7 February 2027 [Page 22]
Internet-Draft JSON Structure Semantic Annotations August 2026
{
"name": "RiverSampleObservation",
"type": "object",
"observedProperty": {
"reference": "https://example.org/props/dissolved-oxygen/v1",
"kind": "example-catalog"
},
"properties": {
"observationId": { "type": "uuid" },
"waterBody": {
"type": "string",
"description": "River water body ultimately of interest",
"examples": ["Rhine", "Niers", "Schwalm"],
"semanticRole": "ultimateFeatureOfInterest"
},
"sampleParcel": {
"type": "string",
"description": "Sampled water parcel directly observed",
"examples": ["Surface sample at station 17"],
"semanticRole": "proximateFeatureOfInterest"
},
"sampler": {
"type": "uri",
"description": "Instrument identifier from a device catalogue",
"examples": [
"https://vocab.nerc.ac.uk/collection/L22/current/TOOL1248/"
],
"semanticRole": "observingProcedure"
},
"dissolvedOxygen": {
"type": "double",
"unit": "mg/L",
"semanticRole": "observationValue"
}
},
"required": [
"observationId", "waterBody", "sampleParcel", "sampler",
"dissolvedOxygen"
],
"additionalProperties": false
}
Vasters Expires 7 February 2027 [Page 23]
Internet-Draft JSON Structure Semantic Annotations August 2026
5.3.2.1. featureOfInterest
Value identifying or describing the feature whose property is
observed: the entity that is the subject of the observation. It is
distinct from observedProperty, which identifies which property is
observed, from observingProcedure, which identifies how the value is
produced, and from observationValue, which carries the result.
The annotated property's value can be a scalar, object, tuple, or
collection. The property schema defines representation, cardinality,
and requiredness.
Where the feature is a member of a collection held elsewhere in the
document, JSON Structure Relations [JSTRUCT-RELATIONS] states the
reference:
{
"definitions": {
"HydroGraph": {
"type": "object",
"name": "HydroGraph",
"properties": {
"riverReaches": {
"type": "array",
"items": { "$ref": "#/definitions/RiverReach" }
},
"observations": {
"type": "array",
"items": { "$ref": "#/definitions/RiverObservation" }
}
},
"required": ["riverReaches", "observations"],
"additionalProperties": false
},
"RiverReach": {
"type": "object",
"name": "RiverReach",
"identity": ["reachId"],
"properties": {
"reachId": { "type": "string" },
"riverName": { "type": "string" },
"fromNodeId": { "type": "string" },
"toNodeId": { "type": "string" },
"lengthMeters": { "type": "double", "unit": "m" }
},
"required": ["reachId", "riverName", "fromNodeId", "toNodeId"],
"additionalProperties": false
},
Vasters Expires 7 February 2027 [Page 24]
Internet-Draft JSON Structure Semantic Annotations August 2026
"RiverObservation": {
"type": "object",
"name": "RiverObservation",
"identity": ["observationId"],
"properties": {
"observationId": { "type": "uuid" },
"reachIdRef": {
"type": "string",
"description": "River reach identifier",
"semanticRole": "featureOfInterest"
},
"waterLevel": {
"type": "double",
"semanticRole": "observationValue",
"unit": "m"
}
},
"relations": {
"featureReachRef": {
"cardinality": "single",
"targettype": { "$ref": "#/definitions/RiverReach" },
"scope": "#/definitions/HydroGraph/properties/riverReaches"
}
},
"required": ["observationId", "reachIdRef", "waterLevel"],
"additionalProperties": false
}
}
}
In an instance, reachIdRef carries the same identifier value used by
the relation target identity, for example "RR-1042".
5.3.2.2. proximateFeatureOfInterest
Value identifying or describing the feature directly involved in
observing.
This role identifies the immediate feature participating in
measurement context (for example a sampled parcel). Where the
observation involves sampling, this is the feature that ISO 19156
[ISO19156] calls a sampling feature.
5.3.2.3. ultimateFeatureOfInterest
Value identifying or describing the feature ultimately of interest.
Vasters Expires 7 February 2027 [Page 25]
Internet-Draft JSON Structure Semantic Annotations August 2026
This role identifies the broader feature for which the observation is
semantically interpreted.
Neither proximate nor ultimate feature is inferred from the other.
When featureOfInterest and specialized FoI roles coexist, processors
MUST preserve them as separate declarations and MUST NOT assume
equivalence. Feature identity MUST NOT be inferred from observation
identity, location, property names, or transport metadata.
5.3.2.4. observingProcedure
Value identifying or describing the procedure used for the
observation act.
Procedure identity is comparability-critical: different procedures
can yield different biases or meanings for the same property and
feature. Equality is evidence for candidate grouping, not proof of
statistical interchangeability. When a shared catalog is available,
procedure identifiers SHOULD be expressed as URIs; a device or
instrument registry serves where the procedure is effectively defined
by the instrument or sampler used.
5.3.3. Temporal Concern (Observation Time)
A record using the roles of this concern:
Vasters Expires 7 February 2027 [Page 26]
Internet-Draft JSON Structure Semantic Annotations August 2026
{
"name": "WaterLevelBulletin",
"type": "object",
"properties": {
"station_id": {
"type": "string",
"semanticRole": "featureOfInterest"
},
"observed_at": {
"type": "datetime",
"description": "Time the water level applied at the station",
"examples": ["2026-07-27T12:00:00Z"],
"semanticRole": "phenomenonTime"
},
"published_at": {
"type": "datetime",
"description": "Time when the result became available",
"examples": ["2026-07-27T12:00:04Z"],
"semanticRole": "resultTime"
},
"in_force": {
"type": "object",
"description": "Period during which the bulletin is in force",
"semanticRole": "effectiveTime",
"properties": {
"start": { "type": "datetime" },
"end": { "type": "datetime" }
},
"required": ["start", "end"],
"additionalProperties": false
},
"water_level": {
"type": "double",
"unit": "m",
"semanticRole": "observationValue"
}
},
"required": [
"station_id", "observed_at", "published_at", "in_force",
"water_level"
],
"additionalProperties": false
}
5.3.3.1. phenomenonTime
Time during which the result applies to the observed property. It
can be represented as an instant or period.
Vasters Expires 7 February 2027 [Page 27]
Internet-Draft JSON Structure Semantic Annotations August 2026
When used for an instant, phenomenonTime MUST annotate a value whose
Core type and reference binding together encode a temporal position.
It MAY instead annotate a named object or tuple representing a
period.
5.3.3.2. resultTime
Temporal position at which the result became available.
resultTime MUST annotate a value whose Core type and reference
binding together encode a temporal position.
5.3.3.3. effectiveTime
Period during which the record is in force and its use is intended.
effectiveTime MAY annotate a named object or tuple representing a
period.
effectiveTime qualifies the record and not the phenomenon. It states
how long a warning, advisory, or other issued statement is meant to
be acted on, and it gives no boundary to any observed property. A
record that describes a period of the world, including a forecast,
states that period with phenomenonTime or with phenomenonTimeStart
and phenomenonTimeEnd. The two are independent: a warning in force
for twelve hours may concern a phenomenon lasting minutes.
This document defines no record-versioning axis. The role is named
effectiveTime rather than validTime because the latter names the
bitemporal valid time of ISO 19108 [ISO19108]. effectiveTime is not
that valid time, which pairs the period a fact is held true of the
world with the period a system recorded it, and a processor MUST NOT
read it as one.
"Time" or "Duration" in any ISO, boundary, or operational role name
defined by this document does not require a Gregorian, ISO 8601, or
RFC 3339 encoding. The semanticRole states semantics; the Core type
and any temporalReferenceSystem state representation and reference
semantics.
5.3.4. Temporal Concern (Flattened Period Boundaries)
A record using the roles of this concern. The two pairs are
independent axes: the phenomenon-time pair bounds what the result is
about, and the effective-time pair bounds how long the record is in
force.
Vasters Expires 7 February 2027 [Page 28]
Internet-Draft JSON Structure Semantic Annotations August 2026
{
"name": "AirQualityAdvisory",
"type": "object",
"properties": {
"site_id": {
"type": "string",
"semanticRole": "featureOfInterest"
},
"averaging_window_opens": {
"type": "datetime",
"examples": ["2026-07-27T12:00:00Z"],
"semanticRole": "phenomenonTimeStart"
},
"averaging_window_closes": {
"type": "datetime",
"examples": ["2026-07-27T13:00:00Z"],
"semanticRole": "phenomenonTimeEnd"
},
"advisory_effective_at": {
"type": "datetime",
"examples": ["2026-07-27T15:00:00Z"],
"semanticRole": "effectiveTimeStart"
},
"advisory_expires_at": {
"type": "datetime",
"examples": ["2026-07-28T03:00:00Z"],
"semanticRole": "effectiveTimeEnd"
},
"mean_pm25": {
"type": "double",
"unit": "ug/m3",
"semanticRole": "observationValue"
}
},
"required": [
"site_id",
"averaging_window_opens",
"averaging_window_closes",
"advisory_effective_at",
"advisory_expires_at",
"mean_pm25"
],
"additionalProperties": false
}
Vasters Expires 7 February 2027 [Page 29]
Internet-Draft JSON Structure Semantic Annotations August 2026
5.3.4.1. phenomenonTimeStart
Temporal position encoding the start of the phenomenonTime period.
phenomenonTimeStart MUST annotate a value whose Core type and
reference binding together encode a temporal position.
5.3.4.2. phenomenonTimeEnd
Temporal position encoding the end of the phenomenonTime period.
phenomenonTimeEnd MUST annotate a value whose Core type and reference
binding together encode a temporal position.
5.3.4.3. effectiveTimeStart
Temporal position encoding the start of the effectiveTime period.
effectiveTimeStart MUST annotate a value whose Core type and
reference binding together encode a temporal position.
5.3.4.4. effectiveTimeEnd
Temporal position encoding the end of the effectiveTime period.
effectiveTimeEnd MUST annotate a value whose Core type and reference
binding together encode a temporal position.
A paired start and end projects one period, not two separate
attributes. Period closure is not supplied by these role names.
This specification uses half-open [start,end) periods only for
phenomenonTimeRelation; another convention requires a separate
representation or profile.
5.3.5. Temporal Concern (Operational Event Time)
A planned activity, its execution, and its acceptance by a receiving
system:
Vasters Expires 7 February 2027 [Page 30]
Internet-Draft JSON Structure Semantic Annotations August 2026
{
"name": "SamplingRun",
"type": "object",
"properties": {
"run_id": { "type": "uuid" },
"scheduled_sample_time": {
"type": "datetime",
"description": "Planned time for sample collection",
"examples": ["2026-07-27T14:00:00Z"],
"semanticRole": "scheduledTime"
},
"actual_sample_time": {
"type": "datetime",
"description": "Time when sample collection actually occurred",
"examples": ["2026-07-27T14:07:12Z"],
"semanticRole": "actualTime"
},
"ingested_at": {
"type": "datetime",
"description": "Time the receiving system accepted the record",
"examples": ["2026-07-27T14:09:30Z"],
"semanticRole": "ingestionTime"
},
"station_id": {
"type": "string",
"semanticRole": "featureOfInterest"
}
},
"required": [
"run_id",
"scheduled_sample_time",
"actual_sample_time",
"ingested_at",
"station_id"
],
"additionalProperties": false
}
5.3.5.1. ingestionTime
Temporal position when a declared system accepted the record.
ingestionTime MUST annotate a value whose Core type and reference
binding together encode a temporal position.
Vasters Expires 7 February 2027 [Page 31]
Internet-Draft JSON Structure Semantic Annotations August 2026
5.3.5.2. scheduledTime
Planned temporal position for an activity.
scheduledTime MUST annotate a value whose Core type and reference
binding together encode a temporal position.
5.3.5.3. actualTime
Temporal position when the planned activity occurred.
actualTime MUST annotate a value whose Core type and reference
binding together encode a temporal position.
5.3.5.4. forecastIssueTime
Forecast-specific resultTime: the temporal position when a forecast
product was issued.
forecastIssueTime MUST annotate a value whose Core type and reference
binding together encode a temporal position.
A forecast record states the position or period it describes with
phenomenonTime, or with phenomenonTimeStart and phenomenonTimeEnd. A
forecast is an observation whose result time precedes its phenomenon
time, and it carries the same temporal roles as any other
observation; nothing about the phenomenon-time roles restricts them
to positions that have already elapsed.
5.3.5.5. forecastLeadDuration
Duration between the forecast issue position and the phenomenon-time
position the forecast describes.
forecastLeadDuration MUST annotate Core duration or a numeric value
with a temporal unit [JSTRUCT-UNITS].
Example:
Vasters Expires 7 February 2027 [Page 32]
Internet-Draft JSON Structure Semantic Annotations August 2026
{
"name": "RiverStageForecast",
"type": "object",
"properties": {
"station_id": {
"type": "string",
"semanticRole": "featureOfInterest"
},
"issued_at": {
"type": "datetime",
"description": "Time when the forecast bulletin was issued",
"examples": ["2026-07-27T09:00:00Z"],
"semanticRole": "forecastIssueTime"
},
"forecast_window": {
"type": "object",
"description": "Phenomenon-time period the forecast describes",
"semanticRole": "phenomenonTime",
"properties": {
"start": { "type": "datetime" },
"end": { "type": "datetime" }
},
"required": ["start", "end"],
"additionalProperties": false
},
"lead_time": {
"type": "duration",
"description": "Duration from issue to the phenomenon time",
"examples": ["PT6H"],
"semanticRole": "forecastLeadDuration"
},
"predicted_water_level": {
"type": "double",
"unit": "m",
"semanticRole": "observationValue"
}
},
"required": [
"station_id", "issued_at", "forecast_window",
"predicted_water_level"
],
"additionalProperties": false
}
These operational values describe the handling of the record. A
processor MUST NOT read any of them as phenomenonTime, resultTime,
observedProperty, featureOfInterest, or observingProcedure.
Vasters Expires 7 February 2027 [Page 33]
Internet-Draft JSON Structure Semantic Annotations August 2026
5.3.6. Status Concern
5.3.6.1. status
State of the record itself, or of the feature it describes, such as
whether a value is provisional, verified, superseded, or withdrawn.
status MUST annotate a value drawn from a fixed set of states, which
is a Core string or an integer type. The states are defined outside
this document. The annotated schema MUST either constrain them with
enum [JSTRUCT-CORE] or identify the set that defines them, which MAY
be a vocabulary referenced via concepts.
status qualifies the record rather than the phenomenon. A change of
status does not change what was observed, and a record MAY be
reissued with a new status and an unchanged result.
status and resultQuality are distinct. resultQuality states how good
a result is, on a scale the quality vocabulary defines; status states
how the record carrying it is to be treated. A provisional record
and a low-quality result are independent conditions, and a processor
MUST NOT read either annotation as the other.
Example:
{
"name": "WaterLevelRecord",
"type": "object",
"properties": {
"water_level": {
"type": "double",
"unit": "m",
"semanticRole": "observationValue"
},
"record_status": {
"type": "string",
"description": "Standing of this record in the lifecycle",
"enum": ["provisional", "verified", "superseded", "withdrawn"],
"examples": ["provisional"],
"semanticRole": "status"
}
},
"required": ["water_level", "record_status"],
"additionalProperties": false
}
Vasters Expires 7 February 2027 [Page 34]
Internet-Draft JSON Structure Semantic Annotations August 2026
5.4. The derivation Keyword
The derivation keyword classifies how a result value was produced.
When present, derivation MUST be one of:
+============+====================================================+
| Derivation | Meaning |
+============+====================================================+
| measured | Produced directly by an observation procedure |
| | performing measurement. |
+------------+----------------------------------------------------+
| statistic | Produced by summarizing a set of values with one |
| | of the functions named by statistic (Section 5.5). |
+------------+----------------------------------------------------+
| calculated | Produced by a deterministic calculation that |
| | statistic does not name. |
+------------+----------------------------------------------------+
| estimated | Inferred from incomplete, indirect, or uncertain |
| | evidence. |
+------------+----------------------------------------------------+
| modeled | Produced by a model, simulation, or predictive |
| | procedure. |
+------------+----------------------------------------------------+
Table 3
Routine conversion, rounding, or serialization does not by itself
change measured to calculated. The category identifies no source,
formula, software, or detailed procedure, and it is not a lineage
model: it does not identify the act that produced the value or relate
that value to the values it was derived from ([PROV-O]).
statistic and calculated divide the calculations between them. Where
the result is one of the summaries this document names, the
derivation is statistic and the statistic keyword names which one, so
a reader can tell an hourly mean from an hourly maximum without
reading prose. Every other calculation is calculated, and the schema
SHOULD explain the method in the description of the annotated schema.
This document defines no expression language, and a processor MUST
NOT parse a description or reproduce a calculation from it.
The names alone do not divide the categories, and the tests below do.
They are stated so that two authors describing the same value reach
the same category.
Vasters Expires 7 February 2027 [Page 35]
Internet-Draft JSON Structure Semantic Annotations August 2026
The first division is between measured and the rest, and it is the
one that carries the most weight for a consumer. A value is measured
where it is what an observation procedure read, and it is not
measured where any function, fit, inference, or model stood between
the procedure and the value. Unit conversion, rounding, and
serialization are not such functions, as stated above.
Determinism divides calculated from estimated and modeled. Where the
same inputs must yield the same output, and the function could be
written down, the value is calculated however elaborate the
arithmetic and however many inputs it consumes. A dew point obtained
from a measured temperature and a measured humidity by a published
formula is calculated.
Dependence on unobserved state divides modeled from estimated. An
estimated value carries only what the observations carry, arranged
under an assumption about their error: an interpolated fill for a
failed sensor, or a strike position derived from arrival times at
several detectors, is estimated, because something was observed and
the value is an inference from evidence that does not determine it.
A modeled value carries information the observations do not contain,
supplied by the model's own representation of the system, and the
procedure would produce a value for a place and time at which nothing
was observed at all. A forecast temperature is modeled. A value
that a model produced and that observations then corrected, as in a
reanalysis or an assimilated field, is modeled, because the model
supplies the state and the observations only constrain it.
Where the choice among calculated, estimated, and modeled is
genuinely unclear, the schema SHOULD state the method in description.
An author MUST NOT resolve such a case by choosing measured, and a
processor MUST NOT infer a formula, a model, an uncertainty, or a
procedure from any of these values.
Example:
Vasters Expires 7 February 2027 [Page 36]
Internet-Draft JSON Structure Semantic Annotations August 2026
{
"name": "SeaStateReport",
"type": "object",
"properties": {
"sea_state_index": {
"type": "double",
"description": "Composite sea-state index",
"semanticRole": "observationValue",
"derivation": "modeled"
}
},
"required": ["sea_state_index"],
"additionalProperties": false
}
5.5. The statistic Keyword
The statistic keyword names the summary function that produced a
result value from a set of values.
Most summary functions are fully identified by their name. A few are
not: a percentile is not one function but a family, and naming the
family without the rank identifies nothing. statistic therefore takes
two forms. A function that takes no parameter is written as a
string, and a function that takes one is written as an object that
names the function and carries the parameter.
When statistic is a string, it MUST be one of:
Vasters Expires 7 February 2027 [Page 37]
Internet-Draft JSON Structure Semantic Annotations August 2026
+===================+==================================+
| Statistic | Meaning |
+===================+==================================+
| mean | Arithmetic mean of the set. |
+-------------------+----------------------------------+
| median | Middle value of the ordered set. |
+-------------------+----------------------------------+
| mode | Most frequent value of the set. |
+-------------------+----------------------------------+
| minimum | Least value of the set. |
+-------------------+----------------------------------+
| maximum | Greatest value of the set. |
+-------------------+----------------------------------+
| sum | Total of the set. |
+-------------------+----------------------------------+
| count | Number of values in the set. |
+-------------------+----------------------------------+
| standardDeviation | Standard deviation of the set. |
+-------------------+----------------------------------+
| variance | Variance of the set. |
+-------------------+----------------------------------+
| range | Difference between the greatest |
| | and least value. |
+-------------------+----------------------------------+
Table 4
When statistic is an object, it MUST carry a function member and the
parameter member that function requires, and no other members.
function MUST be one of:
+============+============+==================================+
| Function | Parameter | Meaning |
+============+============+==================================+
| percentile | percentile | Value below which the stated |
| | | percentage of the set falls. |
+------------+------------+----------------------------------+
| nthHighest | rank | Value at the stated position |
| | | counting down from the greatest. |
+------------+------------+----------------------------------+
| nthLowest | rank | Value at the stated position |
| | | counting up from the least. |
+------------+------------+----------------------------------+
Table 5
Vasters Expires 7 February 2027 [Page 38]
Internet-Draft JSON Structure Semantic Annotations August 2026
percentile MUST be a number greater than zero and less than one
hundred, and rank MUST be an integer of two or more. percentile MUST
be present when function is percentile and MUST NOT be present
otherwise; rank MUST be present when function is nthHighest or
nthLowest and MUST NOT be present otherwise.
Both enumerations are closed. A statistic that is a string outside
the first table, or an object whose function is outside the second,
is invalid.
One meaning has one spelling. A function that takes no parameter
MUST be written in the string form, so { "function": "mean" } is
invalid. A percentile of zero or one hundred MUST be written as
minimum or maximum, and a rank of one MUST be written as maximum or
minimum, which is why the ranges above exclude them. A quantile is
expressed as the equivalent percentile, so a quantile of 0.95 is
written as a percentile of 95. Without these rules two schemas could
declare the same statistic in ways that no equality test would match.
A rank is not a percentile. The fourth-highest value of a set of
three hundred and sixty-five is the 99.18th percentile and of a set
of ninety is the 96.7th, so neither form can be rewritten as the
other without knowing how many values the set held, and statistic
does not state that. Both forms are needed because both are what
definitions in force actually specify: an air quality limit is
commonly expressed as a rank, and a service level objective as a
percentile.
statistic and the statistic derivation are one declaration in two
parts. A schema whose derivation is statistic MUST carry a statistic
keyword, and a schema carrying a statistic keyword MUST have a
derivation of statistic. The derivation says the value summarizes a
set, and the keyword says how. Where phenomenonTimeRelation is
accumulation, statistic MUST be the string sum.
A calculation that no value in either table names is calculated
rather than statistic, and Section 5.4 states what a schema does
instead.
A vocabulary term names the phenomenon and frequently excludes the
summary function, so an hourly mean and an hourly maximum of one
phenomenon carry the same observedProperty and differ only here. Two
results that carry the same observable property and different
statistics are not comparable as like quantities. The parameter is
part of the statistic: a 95th percentile and a 99th percentile are
different statistics, as are a fourth-highest and a fifth-highest,
and a processor MUST NOT treat two parameterized statistics as alike
unless both the function and the parameter agree.
Vasters Expires 7 February 2027 [Page 39]
Internet-Draft JSON Structure Semantic Annotations August 2026
The set that the statistic summarizes is the one the other
annotations already establish: the temporal roles give its extent in
time, and the feature and procedure roles give its subject. This
document defines no other scoping, and the only argument statistic
takes is the one that identifies the function. It does not state a
window alignment, a weighting, a sample count, a treatment of missing
values, an interpolation method by which a percentile is obtained
from a finite set, or a computation, and a processor MUST NOT
recompute a result from it.
Example:
{
"name": "HourlyAirTemperatureSummary",
"type": "object",
"observedProperty": {
"reference":
"http://vocab.nerc.ac.uk/standard_name/air_temperature/",
"kind": "cf-standard-name"
},
"properties": {
"station": {
"type": "string",
"examples": ["DWD-10382"],
"semanticRole": "featureOfInterest"
},
"hour_start": {
"type": "datetime",
"examples": ["2026-07-27T12:00:00Z"],
"semanticRole": "phenomenonTimeStart"
},
"hour_end": {
"type": "datetime",
"examples": ["2026-07-27T13:00:00Z"],
"semanticRole": "phenomenonTimeEnd"
},
"temperature_mean": {
"type": "double",
"unit": "Cel",
"description": "Mean air temperature over the hour",
"examples": [21.4],
"semanticRole": "observationValue",
"derivation": "statistic",
"statistic": "mean"
},
"temperature_max": {
"type": "double",
"unit": "Cel",
Vasters Expires 7 February 2027 [Page 40]
Internet-Draft JSON Structure Semantic Annotations August 2026
"description": "Greatest air temperature over the hour",
"examples": [24.9],
"semanticRole": "observationValue",
"derivation": "statistic",
"statistic": "maximum"
}
},
"required": [
"station", "hour_start", "hour_end", "temperature_mean",
"temperature_max"
],
"additionalProperties": false
}
The record below carries two parameterized statistics of the same
observable over the same interval. They differ only in the
parameter, and nothing but the parameter distinguishes them.
Vasters Expires 7 February 2027 [Page 41]
Internet-Draft JSON Structure Semantic Annotations August 2026
{
"name": "RequestLatencySummary",
"type": "object",
"properties": {
"window_start": {
"type": "datetime",
"examples": ["2026-07-27T12:00:00Z"],
"semanticRole": "phenomenonTimeStart"
},
"window_end": {
"type": "datetime",
"examples": ["2026-07-27T12:05:00Z"],
"semanticRole": "phenomenonTimeEnd"
},
"latency_p95": {
"type": "double",
"unit": "ms",
"description": "Latency below which 95 percent completed",
"examples": [128.4],
"semanticRole": "observationValue",
"derivation": "statistic",
"statistic": { "function": "percentile", "percentile": 95 }
},
"latency_p99": {
"type": "double",
"unit": "ms",
"description": "Latency below which 99 percent completed",
"examples": [512.7],
"semanticRole": "observationValue",
"derivation": "statistic",
"statistic": { "function": "percentile", "percentile": 99 }
}
},
"required": [
"window_start", "window_end", "latency_p95", "latency_p99"
],
"additionalProperties": false
}
The record below carries a rank. The fourth-highest daily maximum is
the form in which an ozone air quality standard is stated, and it is
not the same statistic as any percentile unless the number of days in
the year is known.
Vasters Expires 7 February 2027 [Page 42]
Internet-Draft JSON Structure Semantic Annotations August 2026
========== NOTE: '\' line wrapping per RFC 8792 ===========
{
"name": "AnnualOzoneSummary",
"type": "object",
"observedProperty": {
"reference": "http://vocab.nerc.ac.uk/standard_name/\
mole_fraction_of_ozone_in_air/",
"kind": "cf-standard-name"
},
"properties": {
"site": {
"type": "string",
"examples": ["US-060370016"],
"semanticRole": "featureOfInterest"
},
"year_start": {
"type": "datetime",
"examples": ["2025-01-01T00:00:00Z"],
"semanticRole": "phenomenonTimeStart"
},
"year_end": {
"type": "datetime",
"examples": ["2026-01-01T00:00:00Z"],
"semanticRole": "phenomenonTimeEnd"
},
"fourth_highest_daily_max_8h": {
"type": "double",
"unit": "[ppb]",
"description": "Fourth-highest daily maximum 8-hour mean",
"examples": [68.0],
"semanticRole": "observationValue",
"derivation": "statistic",
"statistic": { "function": "nthHighest", "rank": 4 },
"phenomenonTimeRelation": "interval"
}
},
"required": [
"site", "year_start", "year_end", "fourth_highest_daily_max_8h"
],
"additionalProperties": false
}
6. Coded Value Annotations
Vasters Expires 7 February 2027 [Page 43]
Internet-Draft JSON Structure Semantic Annotations August 2026
6.1. The codedValues Keyword
The codedValues keyword binds the annotated property to a code list,
so that the coded value it carries can be resolved to the meaning the
list assigns it.
A coded value is a number or a short string that stands for a state
in a register maintained elsewhere: a present-weather code, an
airport identifier, a diagnosis code. The register gives each code a
meaning, and the value alone does not. This keyword differs from the
reference-style keywords that bind components to the axes of a space
in that it binds a single value to a list of meanings, and it differs
from concepts in that concepts binds the node to one term while
codedValues binds the property to a whole enumeration that its
instance values draw from.
When present, codedValues MUST be an object with a REQUIRED reference
and a REQUIRED kind, and no other members.
6.1.1. The reference and kind Properties
reference identifies one specific code list. It MUST be an absolute
URI [RFC3986], or, where kind is type, a type reference { "$ref":
<JSON Pointer> } [JSTRUCT-CORE] to a shareable type definition that
enumerates the codes. kind does not name the list; it classifies the
register model the list belongs to, so that a processor knows how the
list is organized and how a value joins to an entry. Several lists
of one model are distinguished by reference, not by kind: the
country, currency, and language tables are three iso lists, and the
location indicators and aircraft type designators are two icao lists.
kind is an open enumeration; the following values are defined here:
Vasters Expires 7 February 2027 [Page 44]
Internet-Draft JSON Structure Semantic Annotations August 2026
+===========+====================================================+
| Kind | Kind of list |
+===========+====================================================+
| wmo-codes | A register in the WMO Codes Registry [WMO-CODES]. |
+-----------+----------------------------------------------------+
| iso | An ISO code table, such as the ISO 3166 country |
| | codes [ISO3166], the ISO 4217 currency codes |
| | [ISO4217], or the ISO 639 language codes [ISO639]. |
+-----------+----------------------------------------------------+
| unlocode | The UN/LOCODE location code list [UNLOCODE]. |
+-----------+----------------------------------------------------+
| icao | An ICAO code list, such as the location indicators |
| | of [ICAO7910] or the aircraft type designators of |
| | [ICAO8643]. |
+-----------+----------------------------------------------------+
| iata | An IATA code directory [IATA-CODES]. |
+-----------+----------------------------------------------------+
| iana | An IANA registry [IANA-PROTOCOLS], such as the |
| | Language Subtag Registry [IANA-LANGTAGS]. |
+-----------+----------------------------------------------------+
| icd | A linearization of the WHO International |
| | Classification of Diseases [WHO-ICD]. |
+-----------+----------------------------------------------------+
| snomed-ct | A SNOMED CT edition or reference set [SNOMED-CT]. |
+-----------+----------------------------------------------------+
| loinc | The LOINC database [LOINC]. |
+-----------+----------------------------------------------------+
| atc | The WHO Anatomical Therapeutic Chemical |
| | classification [WHO-ATC]. |
+-----------+----------------------------------------------------+
| unspsc | The UNSPSC commodity code set [UNSPSC]. |
+-----------+----------------------------------------------------+
| type | A meta-type in the annotated schema whose |
| | enumeration lists the codes, as Section 8 |
| | describes. |
+-----------+----------------------------------------------------+
Table 6
The annotated value MUST be of a scalar type, a string or an integer,
of the kind the identified list uses for its notations. Where kind
is type, the identified type enumerates the code notations, and a
value denotes the entry whose notation it equals.
A value in an instance denotes the entry the register publishes for
that value. How the value is joined to the entry, whether by
appending it to the register URI or by another rule, is stated by the
register and not by this document. Some registers, including
Vasters Expires 7 February 2027 [Page 45]
Internet-Draft JSON Structure Semantic Annotations August 2026
[WMO-CODES], publish each entry at a dereferenceable URI; a reference
to such a register identifies more often than it resolves, which is
true of the other reference-style keywords as well.
A missing or unresolved register is indeterminate and MUST NOT be
repaired from labels, property names, descriptions, or samples. A
value that the register does not define is not made meaningful by
this annotation.
A processor is not required to dereference the URI. This document
does not define a resolution protocol, URI layout, storage model, or
definition serialization.
6.1.2. Example
The property below carries a present-weather code from the WMO
register for present weather, whose entries are the integers zero
through several hundred.
{
"name": "SurfaceObservation",
"type": "object",
"properties": {
"stationId": { "type": "string" },
"presentWeather": {
"type": "int32",
"codedValues": {
"reference": "http://codes.wmo.int/bufr4/codeflag/0-20-003",
"kind": "wmo-codes"
}
}
},
"required": ["stationId", "presentWeather"],
"additionalProperties": false
}
7. Measurement Conditioning Annotations
7.1. The measurementConditioning Keyword
The measurementConditioning keyword states the frequency weighting,
time weighting, and level reference that a scalar measurement
carries, so that two values of the same unit that were conditioned
differently are not compared as like quantities.
A weighted level is a single number, not a bundle of channels, and
its unit does not record how it was made. An A-weighted sound level
and a Z-weighted one are both in decibels, and comparing them is a
Vasters Expires 7 February 2027 [Page 46]
Internet-Draft JSON Structure Semantic Annotations August 2026
mistake the numbers do not prevent. The weighting, the time
constant, and the reference the level stands against are the hidden
convention this keyword carries.
When present, measurementConditioning MUST be an object with an
OPTIONAL weighting, an OPTIONAL timeWeighting, and an OPTIONAL
levelReference, and no other members. At least one of the three MUST
be present. The annotated value MUST be of numeric type.
7.1.1. The weighting Property
weighting, when present, names the frequency weighting the value
carries. It is an open enumeration; the values defined here are the
frequency weightings of [IEC61672-1]:
+=======+====================================+
| Value | Meaning |
+=======+====================================+
| a | A-weighting. |
+-------+------------------------------------+
| c | C-weighting. |
+-------+------------------------------------+
| z | Zero-weighting, the flat response. |
+-------+------------------------------------+
Table 7
7.1.2. The timeWeighting Property
timeWeighting, when present, names the time weighting the value
carries. It is an open enumeration; the values defined here are the
time weightings of [IEC61672-1]:
+=======+======================+
| Value | Meaning |
+=======+======================+
| fast | Fast time weighting. |
+-------+----------------------+
| slow | Slow time weighting. |
+-------+----------------------+
Table 8
The impulse time weighting of the superseded IEC 651 is not among
these; where a legacy dataset needs it, it is carried as an open
value.
Vasters Expires 7 February 2027 [Page 47]
Internet-Draft JSON Structure Semantic Annotations August 2026
7.1.3. The levelReference Property
levelReference, when present, states what the level is relative to.
This is one property appearing in two keywords: the levelReference of
audioChannels (Section 12.1.3) takes the same values with the same
meanings, since both answer the same question about a quantity
expressed on a logarithmic scale.
+===============+=================================================+
| Value | Meaning |
+===============+=================================================+
| soundPressure | The reference is 20 micropascals [ISO1683], and |
| | a level in decibels is sound pressure level. |
+---------------+-------------------------------------------------+
| fullScale | The reference is digital full scale, the |
| | greatest level the representation admits, and a |
| | level in decibels is dBFS. |
+---------------+-------------------------------------------------+
Table 9
The enumeration is open. A value outside it MUST be an absolute URI
[RFC3986] identifying another reference, because a level may be
referred to a voltage, a power, or a quantity that the standard
governing an instrument fixes, and this document does not enumerate
what other bodies define. A processor that does not know a value
MUST preserve it, MUST NOT reject the schema for carrying it, and
MUST NOT compare a level against one carrying a different reference.
7.1.4. Example
The property below carries an A-weighted, fast, sound-pressure level.
Vasters Expires 7 February 2027 [Page 48]
Internet-Draft JSON Structure Semantic Annotations August 2026
{
"name": "NoiseReading",
"type": "object",
"properties": {
"sensorId": { "type": "string" },
"soundLevel": {
"type": "double",
"unit": "dB",
"measurementConditioning": {
"weighting": "a",
"timeWeighting": "fast",
"levelReference": "soundPressure"
}
}
},
"required": ["sensorId", "soundLevel"],
"additionalProperties": false
}
8. Reference System Meta-Types
A reference system need not be published by an authority. Where the
kind of a reference-system keyword is type, reference is a type
reference { "$ref": <JSON Pointer> } [JSTRUCT-CORE] to a shareable
type definition, and that type definition is the definition of the
system. Such a type is a meta-type. It is ordinarily maintained in
its own document and brought into definitions with $import
[JSTRUCT-IMPORT], so that one definition serves every schema that
cites it.
A meta-type declares the members of the system, and the annotation
maps the members of the annotated schema onto them. The two need not
agree in member names, member order, or member count.
A meta-type is an ordinary type definition that a schema author
writes, and it is unrelated to the extension meta-schema of
Section 14, which is the schema of this specification.
8.1. The referenceRole Keyword
referenceRole states the function of a member within a meta-type. It
MAY occur on a property, collection item, map value, or choice member
schema of a type that a reference identifies, and it establishes
nothing elsewhere.
When present, referenceRole MUST be one of:
Vasters Expires 7 February 2027 [Page 49]
Internet-Draft JSON Structure Semantic Annotations August 2026
+===============+=====================================+
| Value | Function of the member |
+===============+=====================================+
| position | Carries a temporal position, mapped |
| | by position (Section 9.3). |
+---------------+-------------------------------------+
| linearElement | Identifies a linear element, mapped |
| | by linearElement (Section 10.5). |
+---------------+-------------------------------------+
| measure | Carries a distance along a linear |
| | element, mapped by measure. |
+---------------+-------------------------------------+
| direction | Qualifies direction of travel or |
| | orientation, mapped by direction. |
+---------------+-------------------------------------+
Table 10
One meta-type MUST NOT declare two members with the same
referenceRole. A member without referenceRole is a component of the
system that no annotation maps, and an annotated schema MAY carry it,
under any name, or omit it.
A mapping is established by referenceRole and never by a member name.
A processor MUST NOT infer a role from the name of a member, and a
meta-type that declares no member for a role a keyword requires is
unusable by that keyword.
A coordinate reference system takes no roles, because its meta-type
is a tuple and the order of its elements establishes the axes
(Section 10.1). A vector reference frame takes no roles for the same
reason (Section 10.2).
9. Temporal Reference Annotations
The keywords in this section concern temporal positions, the values
that place an observation or an operational event on a time line.
phenomenonTimeRelation states how a result relates to the position it
accompanies, supportPeriod gives the length of the period a result
characterizes where the record bounds it at one end,
temporalReferenceSystem states how a position value is to be read,
and cadence states how successive positions are expected to recur.
Vasters Expires 7 February 2027 [Page 50]
Internet-Draft JSON Structure Semantic Annotations August 2026
9.1. The phenomenonTimeRelation Keyword
The phenomenonTimeRelation keyword refines how a result value relates
to phenomenonTime. When semanticRole: observationValue is also
present, it describes the observation result. It is not a
replacement for phenomenonTime.
When present, it MUST be one of:
+==============+============================================+
| Value | Meaning |
+==============+============================================+
| instant | Result applies at the sibling temporal |
| | position having role phenomenonTime. |
+--------------+--------------------------------------------+
| untilNext | Result applies from that position until |
| | the next actual compatible observation. |
+--------------+--------------------------------------------+
| interval | Result characterizes a half-open |
| | phenomenon-time period the record encodes. |
+--------------+--------------------------------------------+
| accumulation | Result is accumulated over that half-open |
| | phenomenon-time period. |
+--------------+--------------------------------------------+
Table 11
instant and untilNext can be resolved only when a sibling
phenomenonTime annotation identifies a temporal position. interval
and accumulation can be resolved when sibling phenomenonTimeStart and
phenomenonTimeEnd annotations identify boundaries in a common
reference regime or through an authoritative conversion, and can be
resolved when supportPeriod states the length of the period and a
sibling position anchors it (Section 9.2). Otherwise the support is
declared but its temporal extent is indeterminate. Effective-time
and operational roles do not supply phenomenon-time boundaries.
These values state how a result relates to a phenomenon time and not
how it was produced; the summary function, where there is one, is
carried by statistic (Section 5.5). They do not authorize summation
or prove complete coverage. For untilNext, the successor is the next
actual observation with compatible resolved feature of interest,
observed property, declared procedure, value type, unit, temporal
binding, and support. Cadence does not prove a successor exists;
without one the support end is unknown. Omission is not instant.
Vasters Expires 7 February 2027 [Page 51]
Internet-Draft JSON Structure Semantic Annotations August 2026
Example. air_temperature holds until the next compatible observation,
so it reads against the sibling phenomenonTime; rainfall is
accumulated over the period, so it reads against the sibling boundary
pair:
{
"name": "WeatherReport",
"type": "object",
"properties": {
"observed_at": {
"type": "datetime",
"semanticRole": "phenomenonTime"
},
"window_opens": {
"type": "datetime",
"semanticRole": "phenomenonTimeStart"
},
"window_closes": {
"type": "datetime",
"semanticRole": "phenomenonTimeEnd"
},
"air_temperature": {
"type": "double",
"unit": "Cel",
"semanticRole": "observationValue",
"phenomenonTimeRelation": "untilNext"
},
"rainfall": {
"type": "double",
"unit": "mm",
"semanticRole": "observationValue",
"phenomenonTimeRelation": "accumulation"
}
},
"required": [
"observed_at",
"window_opens",
"window_closes",
"air_temperature",
"rainfall"
],
"additionalProperties": false
}
Vasters Expires 7 February 2027 [Page 52]
Internet-Draft JSON Structure Semantic Annotations August 2026
9.2. The supportPeriod Keyword
The supportPeriod keyword states the length of the phenomenon-time
period a result characterizes, for a period the record bounds at one
end rather than two. A mean wind speed over the ten minutes ending
at the observation time, a half-hourly settlement quantity stamped
with the instant its period opens, and a pressure change over the
preceding three hours are all of that shape: the length is fixed by
the publishing arrangement, and one position in the record fixes
where the period sits. Such a feed carries no second boundary and
gains nothing from a schema that invents a member for one.
When present, supportPeriod MUST be an object with a REQUIRED length
and a REQUIRED anchor. No other properties are permitted.
9.2.1. The length Property
length states the extent of the period and MUST express a positive
interval in the temporal reference system applicable to the anchoring
position. For a Core datetime, date, or time, it MUST be a positive
Core duration. Another temporal reference system MAY use a numeric,
string, or structured interval representation defined by that system,
on the terms Section 9.4 states for period.
9.2.2. The anchor Property
anchor states which boundary of the period the anchoring position
occupies and MUST be one of:
+=======+=====================================+
| Value | Meaning |
+=======+=====================================+
| start | The anchoring position opens the |
| | period, which runs forward from it. |
+-------+-------------------------------------+
| end | The anchoring position closes the |
| | period, which runs back to it. |
+-------+-------------------------------------+
Table 12
The anchoring position is the sibling annotated phenomenonTimeStart
when anchor is start, and the sibling annotated phenomenonTimeEnd
when anchor is end. Where the record carries no member in that role,
the anchoring position is the sibling annotated phenomenonTime.
Where it carries neither, the period has a length and no location,
and the extent remains indeterminate.
Vasters Expires 7 February 2027 [Page 53]
Internet-Draft JSON Structure Semantic Annotations August 2026
The period is half-open on the terms Section 9.1 states. For an
anchoring position t, an anchor of end gives [t - length, t) and an
anchor of start gives [t, t + length).
supportPeriod MUST NOT be present unless phenomenonTimeRelation is
interval or accumulation, and MUST NOT be present where sibling
phenomenonTimeStart and phenomenonTimeEnd annotations both identify
boundaries, because the record then encodes the period and a stated
length would restate or contradict it.
The boundary roles do not subsume this keyword. phenomenonTimeStart
and phenomenonTimeEnd annotate members, so they state a period only
where the record carries a value at each end of it, and the
resolution rules of this document read one sibling in each role.
Support is a property of a result rather than of a record, and one
record may carry results of differing extent: a buoy report may close
a twenty-minute wave summary and a three-hour pressure change at a
single observation time, leaving one place to put a boundary and two
periods to state. supportPeriod is carried by the result it
describes, so each result states its own extent, and a length fixed
by the publishing arrangement is stated once in the schema rather
than transmitted in every record.
A support period is a fact about one value and a cadence is a fact
about a producer. The two are often numerically equal and are never
the same statement. A station reporting hourly a mean taken over the
last ten minutes of each hour has a cadence of one hour and a support
period of ten minutes, and a schema declaring only the cadence would
leave a reader free to treat fifty minutes of every hour as observed.
cadence does not bound a phenomenon time (Section 9.4), and
supportPeriod asserts nothing about whether a successor record exists
or when it arrives.
Where the length is not fixed by the schema, because it varies with
the station, the instrument, or the message, there is no length to
state and a schema MUST NOT state a nominal one. The extent is then
indeterminate, and a schema SHOULD record in description what governs
the length, so that a reader learns where to obtain it rather than
assuming a value.
Example. A surface report carries a mean wind speed over the ten
minutes ending at the observation time and a rainfall total
accumulated over the hour that opens at the stated instant. The
record has one boundary member and two periods:
Vasters Expires 7 February 2027 [Page 54]
Internet-Draft JSON Structure Semantic Annotations August 2026
{
"name": "SurfaceReport",
"type": "object",
"properties": {
"observed_at": {
"type": "datetime",
"examples": ["2026-07-27T12:50:00Z"],
"semanticRole": "phenomenonTime"
},
"accumulation_opens": {
"type": "datetime",
"examples": ["2026-07-27T12:00:00Z"],
"semanticRole": "phenomenonTimeStart"
},
"wind_speed": {
"type": "double",
"unit": "m/s",
"semanticRole": "observationValue",
"derivation": "statistic",
"statistic": "mean",
"phenomenonTimeRelation": "interval",
"supportPeriod": { "length": "PT10M", "anchor": "end" }
},
"rainfall": {
"type": "double",
"unit": "mm",
"semanticRole": "observationValue",
"derivation": "measured",
"phenomenonTimeRelation": "accumulation",
"supportPeriod": { "length": "PT1H", "anchor": "start" }
}
},
"required": [
"observed_at",
"accumulation_opens",
"wind_speed",
"rainfall"
],
"additionalProperties": false
}
The record carries no phenomenonTimeEnd, so wind_speed anchors on
observed_at and covers [12:40Z, 12:50Z). rainfall anchors on
accumulation_opens and covers [12:00Z, 13:00Z). The two periods
overlap and neither is the other, and a reader that took the
observation instant for both would attribute the hour's rain to ten
minutes of it.
Vasters Expires 7 February 2027 [Page 55]
Internet-Draft JSON Structure Semantic Annotations August 2026
9.3. The temporalReferenceSystem Keyword
The temporalReferenceSystem keyword identifies the temporal reference
definition needed to interpret an encoded temporal position or
duration.
It attaches to a temporally typed property or to a type definition
that serves as one. Where that type is an object or tuple, position
names the member that carries the position value.
When present, temporalReferenceSystem MUST be an object with a
REQUIRED reference string, a REQUIRED kind string, an OPTIONAL
position string, and an OPTIONAL sortOrder string. No other
properties are permitted.
Core temporal types need no annotation when their Core semantics are
fully intended. A non-Core or ambiguous encoding is indeterminate
without one.
9.3.1. The reference Property
reference MUST identify one temporal reference definition. Where
kind is type it MUST be a type reference { "$ref": <JSON Pointer> }
[JSTRUCT-CORE] to a shareable type definition, and otherwise it MUST
be an absolute URI [RFC3986]. kind states which definition model the
reference identifies. This document does not define a resolution
protocol, URI layout, storage model, or definition serialization.
Where the identified definition has a domain of validity, an
annotated position MUST lie in that domain.
9.3.2. The kind Property
kind classifies which definition model the URI identifies. It is an
open enumeration. The following values are defined here:
Vasters Expires 7 February 2027 [Page 56]
Internet-Draft JSON Structure Semantic Annotations August 2026
+==================+========================================+
| Kind | Referenced definition |
+==================+========================================+
| ogc-trs | A concept in the OGC temporal |
| | reference system register, whose |
| | entries follow ISO 19108 [ISO19108]. |
+------------------+----------------------------------------+
| ogc-temporal-crs | A GML TemporalCRS served by the OGC |
| | definitions server, establishing a |
| | temporal datum, origin, and coordinate |
| | system [ISO19111] [OGC-TOPIC2]. |
+------------------+----------------------------------------+
| type | A meta-type declaring a member whose |
| | referenceRole is position, alongside |
| | the components of the regime |
| | (Section 8). |
+------------------+----------------------------------------+
Table 13
Other values MAY name further definition models. Appendix A lists
resolvable URIs for the registered kinds.
Whichever model a kind names, the identified definition MUST
establish the components applicable to the encoding it governs.
Where it defines a compound regime that locates a position by scoped
components [OGC-TOPIC25], it MUST state component order, the scope
and reset behavior of each component, and the rules for comparing
positions from different scopes.
A type reference carries a regime that no register holds. The
referenced meta-type MUST declare a member whose referenceRole is
position, and the type and unit of that member establish the
encoding. The position property maps the annotated member onto it.
The remaining members of the meta-type are components of the regime
that the annotation does not map. What a type definition cannot
express, such as reset behavior and comparison across scopes, is
stated in its description.
9.3.3. The position Property
position is REQUIRED when the annotation is attached to an object or
tuple and is prohibited otherwise. It MUST name a direct member of
that object or tuple, and that member MUST be REQUIRED.
The named member carries the temporal position. Its values MUST sort
in the direction given by sortOrder under the ordering defined for
its own type, which for a string is lexical order. A compound
Vasters Expires 7 February 2027 [Page 57]
Internet-Draft JSON Structure Semantic Annotations August 2026
position achieves this by rendering its components most significant
first at fixed width. A processor can therefore order and compare
positions without implementing the referenced definition.
The remaining members MAY hold the individual components,
identifiers, or other detail. A processor is not required to
interpret them.
9.3.4. The sortOrder Property
sortOrder states how the ordering of the encoded value runs relative
to temporal order. When present, it MUST be one of:
+==========+=============================================+
| Value | Ordering |
+==========+=============================================+
| forward | An increasing value is a later position. |
+----------+---------------------------------------------+
| backward | An increasing value is an earlier position. |
+----------+---------------------------------------------+
Table 14
When sortOrder is absent, the value is forward.
Most definitions count from an epoch toward the present and are
therefore forward. An annotation citing a definition whose values
count away from a datum into the past, such as years before present
or a geologic time scale, MUST declare sortOrder as backward.
sortOrder applies to the annotated value, or to the member named by
position where one is named. It states the direction of the ordering
and nothing else, and a definition whose values do not order under
their own type at all is not made orderable by declaring either
value.
9.3.5. Type Compatibility
The referenced definition establishes an encoding, and the annotated
schema MUST be able to carry it:
Vasters Expires 7 February 2027 [Page 58]
Internet-Draft JSON Structure Semantic Annotations August 2026
+========================================+=========================+
| Encoding established by the definition | Compatible schema |
+========================================+=========================+
| A date and time in a calendar, | Core datetime, date, |
| following [RFC3339] | time, or string |
+----------------------------------------+-------------------------+
| A count of units elapsed from an epoch | a Core integer or |
| | number type |
+----------------------------------------+-------------------------+
| Any other encoding | string, or an object or |
| | tuple carrying position |
+----------------------------------------+-------------------------+
Table 15
Where the definition establishes a unit for its axis, a numeric
position MUST carry a unit or ucumUnit annotation compatible with
that unit. Epoch definitions differ in unit, so a count of seconds
and a count of milliseconds from the same origin are distinct
definitions rather than one definition with two encodings.
How much of this a reader can check depends on kind. An ogc-
temporal-crs definition determines the encoding, since its axis
states either a unit of measure, which takes a numeric position, or a
date and time, which takes a string. A type definition declares the
type of each component and likewise determines it. An ogc-trs
concept names a time scale and establishes no axis, unit, or
encoding, so the compatibility check is indeterminate, as it is for a
kind outside this enumeration.
The annotation does not change the JSON base type, turn a data value
into an identifiable temporal object, or supply a conversion. A
processor MUST compare, order, or combine positions only within the
same binding or through an authoritative transformation. A position
whose definition establishes only order MUST NOT be treated as a
metric coordinate without additional authority. Property names alone
establish none of these semantics.
Example. The clock is defined once as a meta-type and cited by
reference, so a record of another shape can name the same definition.
The record names the mapped member ordinal rather than clockPosition,
and position establishes the mapping; the remaining components are
carried under the record's own names and are not mapped. ordinal
renders the components at fixed width, so a processor can order two
positions without implementing the definition.
Vasters Expires 7 February 2027 [Page 59]
Internet-Draft JSON Structure Semantic Annotations August 2026
{
"$schema":
"https://json-structure.org/meta/semantic-annotations/v0/#",
"$id": "https://schemas.example.org/racing-speed-observation",
"name": "RacingSpeedObservation",
"type": "object",
"identity": ["observation_id"],
"observedProperty": {
"reference": "https://example.org/props/vehicle-speed/v1",
"kind": "example-catalog"
},
"properties": {
"observation_id": { "type": "uuid" },
"entry_id": {
"type": "string",
"semanticRole": "featureOfInterest"
},
"race_clock": {
"type": "object",
"semanticRole": "phenomenonTime",
"temporalReferenceSystem": {
"reference": { "$ref": "#/definitions/RaceClockPosition" },
"kind": "type",
"position": "ordinal"
},
"properties": {
"ordinal": {
"type": "string",
"description": "Fixed-width position, ordered lexically",
"examples": ["2026-07-26/R/S03/L014/01250.5"]
},
"session": { "type": "string" },
"stint": { "type": "uint32" },
"lap": { "type": "uint32" },
"distance_driven": { "type": "double", "unit": "m" }
},
"required": [
"ordinal", "session", "stint", "lap", "distance_driven"
],
"additionalProperties": false
},
"speed": {
"type": "double",
"unit": "km/h",
"semanticRole": "observationValue",
"phenomenonTimeRelation": "instant",
"derivation": "measured"
}
Vasters Expires 7 February 2027 [Page 60]
Internet-Draft JSON Structure Semantic Annotations August 2026
},
"required": ["observation_id", "entry_id", "race_clock", "speed"],
"additionalProperties": false,
"definitions": {
"RaceClockPosition": {
"name": "RaceClockPosition",
"type": "object",
"description": "Motor-racing clock.",
"properties": {
"clockPosition": {
"type": "string",
"description": "Fixed-width components, sorting lexically",
"referenceRole": "position"
},
"session": { "type": "string" },
"stint": { "type": "uint32" },
"lap": { "type": "uint32" },
"distanceDriven": { "type": "double", "unit": "m" }
},
"required": ["clockPosition"]
}
}
}
The clock locates a position by session, stint, lap, and distance
driven within the lap, with the components rendered most significant
first in clockPosition. Stint numbering is entry-specific.
The compound position is comparable only under the rules of the
identified regime: equal stint, lap, and distance values do not imply
equal positions across sessions or entries. Mapping this clock to
UTC or elapsed session time requires an authoritative synchronization
relation or transformation.
9.4. The cadence Keyword
The cadence keyword describes expected producer behavior across
successive values of an annotated temporal position. A temporal role
such as phenomenonTime, resultTime, ingestionTime, or
forecastIssueTime, when also present, gives that sequence an
observation or operational meaning.
When present, cadence MUST be an object with a REQUIRED kind string
and an OPTIONAL period. No other properties are permitted.
Vasters Expires 7 February 2027 [Page 61]
Internet-Draft JSON Structure Semantic Annotations August 2026
9.4.1. The kind Property
kind states the expected recurrence pattern and MUST be one of:
+===========+====================================================+
| Kind | Meaning |
+===========+====================================================+
| fixed | Observations are expected at a regular period. |
+-----------+----------------------------------------------------+
| irregular | Observations occur without a regular period. |
+-----------+----------------------------------------------------+
| onChange | Observations occur when represented state changes. |
+-----------+----------------------------------------------------+
Table 16
9.4.2. The period Property
period is REQUIRED when kind is fixed and is prohibited otherwise.
It MUST express a positive interval in the temporal reference system
applicable to the annotated temporal position. For a Core datetime,
date, or time, it MUST be a positive Core duration. Another temporal
reference system MAY use a numeric, string, or structured interval
representation defined by that system.
That latitude is what makes a rapid cadence expressible, and a schema
for one SHOULD use it rather than force the period into civil time.
A duration is written in seconds and their decimal fractions, and
many rates that are exact on their own clock have no exact expression
there: audio sampled at 48 kHz advances one frame every 1/48000 of a
second, so any duration written for it is rounded, and a consumer
that places positions by accumulating it drifts further from the
truth with every frame. Writing the period more exactly does not
help, because civil time cannot express the instants either. A
stream whose positions are counted is not a stream whose positions
are seconds.
Where the values are counted on a clock of their own, the schema
declares that clock as a meta-type, names it in
temporalReferenceSystem (Section 9.3), and gives period as a count of
that clock's own units, which for a value recorded once per tick is
the integer 1. The cadence is then exact, because it is stated in
the system the values are expressed in.
Vasters Expires 7 February 2027 [Page 62]
Internet-Draft JSON Structure Semantic Annotations August 2026
The conversion to seconds is data rather than annotation. A rate
varies from one delivery to the next while the schema stays the same,
so a member of the record carries it, annotated with a unit
[JSTRUCT-UNITS], and a consumer MUST NOT assume a conventional value
for it. Where a schema serves one rate and no other, const or enum
[JSTRUCT-CORE] pins the value on that member.
No keyword binds a clock to the member carrying its rate. A
processor MUST NOT take a member to be the rate of a clock because of
the member's name or because its unit is one of frequency, and MUST
NOT convert a position counted on such a clock to elapsed civil time
unless a relation to civil time is established outside these
annotations. The meta-type declaring the clock states that relation,
or its absence, in its description (Section 9.3).
Cadence is not delivery time, a service-level objective, a
completeness assertion, or a phenomenon-time boundary. It does not
assert that every position has a record, that records arrive in
order, or that an untilNext successor exists.
Cadence is an expectation and not a constraint, and the distinction
is normative. A schema that declares a cadence constrains no
instance document. An instance whose values do not follow the
declared cadence is not invalid for that reason, because a stream
that misses a beat is late rather than malformed, and a processor
MUST NOT reject an instance, a value, or a schema on the ground that
observed timing departs from a declared cadence. A runtime service
level belongs to an agreement between a producer and a consumer, not
to a schema.
A consumer may still act on a cadence. A declared period sizes a
window, sets a threshold beyond which a value is treated as stale,
and makes an absent value detectable as a gap rather than absorbed
silently. Each of those is a decision the consumer makes about its
own processing. None of them changes the meaning of a value, and
none licenses a value to be supplied where none was recorded
(Section 15).
Example:
Vasters Expires 7 February 2027 [Page 63]
Internet-Draft JSON Structure Semantic Annotations August 2026
{
"name": "WindSpeedObservation",
"type": "object",
"properties": {
"measured_at": {
"type": "datetime",
"description": "Instant to which the wind speed applies",
"examples": ["2026-07-27T12:10:00Z"],
"semanticRole": "phenomenonTime",
"cadence": {
"kind": "fixed",
"period": "PT10M"
}
},
"wind_speed": {
"type": "double",
"unit": "m/s",
"semanticRole": "observationValue"
}
},
"required": ["measured_at", "wind_speed"],
"additionalProperties": false
}
A cadence too rapid for civil time, stated on a clock of its own:
Vasters Expires 7 February 2027 [Page 64]
Internet-Draft JSON Structure Semantic Annotations August 2026
{
"name": "AudioSampleFrame",
"type": "object",
"properties": {
"frame_index": {
"type": "int64",
"description": "Sample count from the start of delivery",
"semanticRole": "phenomenonTime",
"temporalReferenceSystem": {
"reference": { "$ref": "#/definitions/AudioSampleClock" },
"kind": "type",
"sortOrder": "forward"
},
"cadence": {
"kind": "fixed",
"period": 1
}
},
"sample_rate": {
"type": "int32",
"unit": "Hz",
"description": "Sample frames per second for this delivery"
},
"amplitude": {
"type": "double",
"semanticRole": "observationValue"
}
},
"required": ["frame_index", "sample_rate", "amplitude"],
"additionalProperties": false,
"definitions": {
"AudioSampleClock": {
"name": "AudioSampleClock",
"type": "object",
"description": "Sample-frame count clock for one delivery.",
"properties": {
"frame_count": {
"type": "int64",
"description": "Sample count from the start of delivery.",
"referenceRole": "position"
}
},
"required": ["frame_count"],
"additionalProperties": false
}
}
}
Vasters Expires 7 February 2027 [Page 65]
Internet-Draft JSON Structure Semantic Annotations August 2026
The clock advances one unit per frame and does not reset within a
delivery, so positions sort numerically and are comparable within one
delivery and not across deliveries. Elapsed seconds are the count
divided by the frame rate of the delivery, which the meta-type does
not supply.
The cadence here is one sample-clock unit and is exact. Written as a
duration it could only have been approximated: PT0.0000208333S is
short of a forty-eight-kilohertz frame by about thirty-three
picoseconds, which is nothing in one frame and a full sample every
thirteen seconds of programme, growing without bound for as long as
the recording runs.
10. Spatial Reference Annotations
Each keyword in this section has two parts. reference and kind
identify an external definition of a reference system. The remaining
properties bind the components of that system to named members of the
object or tuple carrying the annotation. A position or a vector is
held across several members, so these keywords attach to a complex
type and are not meaningful on a scalar.
10.1. The coordinateReferenceSystem Keyword
The coordinateReferenceSystem keyword identifies the coordinate
reference system [ISO19111] under which coordinate values held in
properties of an object or tuple are to be interpreted.
When present, coordinateReferenceSystem MUST be an object with a
REQUIRED reference string, a REQUIRED kind string, and a REQUIRED
coordinates array. No other properties are permitted.
10.1.1. The reference Property
reference MUST identify one coordinate reference system whose
definition establishes an ordered set of axes, each with an axis
direction and unit of measure. Where kind is type it MUST be a type
reference { "$ref": <JSON Pointer> } [JSTRUCT-CORE] to a shareable
type definition, and otherwise it MUST be an absolute URI [RFC3986].
kind states which definition model the reference identifies.
A processor is not required to dereference the URI, and a returned
representation need not expose the axes. This document does not
define a resolution protocol, URI layout, storage model, or
definition serialization.
Vasters Expires 7 February 2027 [Page 66]
Internet-Draft JSON Structure Semantic Annotations August 2026
10.1.2. The kind Property
kind classifies which definition model the URI identifies. It is an
open enumeration. The following values are defined here:
+=========+==========================================+
| Kind | Referenced definition |
+=========+==========================================+
| ogc-crs | A GML CRS served by the OGC definitions |
| | server, named according to the OGC name |
| | type specification [OGC-NAMES]. |
+---------+------------------------------------------+
| epsg | A record in the EPSG Geodetic Parameter |
| | Dataset [EPSG]. |
+---------+------------------------------------------+
| type | A meta-type that is a tuple whose |
| | elements in order are the axes of an |
| | engineering or local system (Section 8). |
+---------+------------------------------------------+
Table 17
Other values MAY name further definition models.
A type reference carries an engineering or local system that no
register holds. The referenced meta-type MUST be a tuple, and the
order given by its tuple keyword is the axis order. coordinates maps
the annotated properties onto those elements by position, so the
number of names in coordinates MUST equal the number of elements and
each element establishes the unit of its axis. Axis direction,
datum, and origin are stated in the description of the meta-type or
of its elements.
Schema authors SHOULD use a registered definition where one exists.
Appendix A lists resolvable URIs for the registered kinds.
10.1.3. The coordinates Property
coordinates MUST be a non-empty ordered array of distinct property
names. Every name MUST resolve to a direct property of the annotated
object or tuple. The property at array index zero supplies axis 1 of
the referenced coordinate system, the property at index one supplies
axis 2, and so on. The number of names MUST equal the dimension of
that coordinate system.
This ordering is an assertion by the schema author. It is not
inferred from property names or from a representation returned by
dereferencing reference.
Vasters Expires 7 February 2027 [Page 67]
Internet-Draft JSON Structure Semantic Annotations August 2026
A name in coordinates MAY resolve to a property whose type is array
or tuple. Where it does resolve to an array, that name MUST be the
only entry in coordinates, and the elements of the array instances
MUST supply the axes in order rather than the named property
supplying one axis.
For a tuple, the number of elements MUST equal the dimension of the
referenced system. A schema using an array SHOULD constrain its
length. The axes of a coordinate reference system may carry
differing units, which a tuple can state per element and an array
cannot.
Coordinate properties MUST have numeric types. When a coordinate
property has a unit or ucumUnit annotation, that unit MUST be
compatible with the corresponding axis. A processor MAY verify the
asserted ordering, units, and dimension using a trusted authority-
specific CRS database. Without such a definition source, it MUST
preserve the declaration but treat those checks and coordinate
transformations as indeterminate.
Properties not named by coordinates are not part of the coordinate.
The annotation therefore applies safely to an existing object that
also contains identity, temporal, status, or other values.
An object or tuple MUST NOT carry more than one
coordinateReferenceSystem annotation. An object containing multiple
coordinates SHOULD model each coordinate as a nested object. This
document does not define coordinate epochs for dynamic coordinate
reference systems.
The coordinate order is significant. OGC CRS84 uses longitude,
latitude:
Vasters Expires 7 February 2027 [Page 68]
Internet-Draft JSON Structure Semantic Annotations August 2026
{
"name": "Crs84Position",
"type": "object",
"coordinateReferenceSystem": {
"reference": "http://www.opengis.net/def/crs/OGC/1.3/CRS84",
"kind": "ogc-crs",
"coordinates": ["lon", "lat"]
},
"properties": {
"lat": {
"type": "double",
"unit": "deg"
},
"lon": {
"type": "double",
"unit": "deg"
}
},
"required": ["lat", "lon"],
"additionalProperties": false
}
EPSG:4326 [EPSG] uses its authoritative latitude, longitude axis
order:
{
"name": "Epsg4326Position",
"type": "object",
"coordinateReferenceSystem": {
"reference": "http://www.opengis.net/def/crs/EPSG/0/4326",
"kind": "ogc-crs",
"coordinates": ["lat", "lon"]
},
"properties": {
"lat": {
"type": "double",
"unit": "deg"
},
"lon": {
"type": "double",
"unit": "deg"
}
},
"required": ["lat", "lon"],
"additionalProperties": false
}
Vasters Expires 7 February 2027 [Page 69]
Internet-Draft JSON Structure Semantic Annotations August 2026
10.1.4. Vertical and Compound Systems
A vertical coordinate reference system has one axis, and coordinates
then names one property. This is the binding that makes a height or
a depth interpretable, because the number and its unit do not state
what the value is measured from.
The axis direction comes from the referenced definition and not from
the annotation, so whether the axis is positive up or positive down
is a fact about the identified system. Where kind is type, the
description of the meta-type or of its elements states it.
The following excerpt binds a gauge reading to NAVD88 height:
{
"name": "GaugeHeightObservation",
"type": "object",
"coordinateReferenceSystem": {
"reference": "http://www.opengis.net/def/crs/EPSG/0/5703",
"kind": "ogc-crs",
"coordinates": ["water_level"]
},
"properties": {
"station": {
"type": "string",
"description": "Observed gauging station",
"examples": ["USGS-12149000"],
"semanticRole": "featureOfInterest"
},
"measured_at": {
"type": "datetime",
"examples": ["2026-07-27T12:00:00Z"],
"semanticRole": "phenomenonTime"
},
"water_level": {
"type": "double",
"unit": "m",
"description": "Water surface elevation",
"examples": [2.47],
"semanticRole": "observationValue"
}
},
"required": ["station", "measured_at", "water_level"],
"additionalProperties": false
}
Vasters Expires 7 February 2027 [Page 70]
Internet-Draft JSON Structure Semantic Annotations August 2026
Where a horizontal position and a height belong to one compound
system, that system has one definition and one set of axes, so a
single annotation names all of them in order. The annotation of such
an object reads:
{
"coordinateReferenceSystem": {
"reference": "http://www.opengis.net/def/crs/EPSG/0/6349",
"kind": "ogc-crs",
"coordinates": ["lat", "lon", "height"]
}
}
Where the height belongs to a different system from the horizontal
position, or where it is a result rather than part of a position, the
two are separate bindings. Since an object carries at most one
coordinateReferenceSystem, the schema models one of them as a nested
object:
Vasters Expires 7 February 2027 [Page 71]
Internet-Draft JSON Structure Semantic Annotations August 2026
{
"name": "StationWaterLevel",
"type": "object",
"coordinateReferenceSystem": {
"reference": "http://www.opengis.net/def/crs/EPSG/0/5703",
"kind": "ogc-crs",
"coordinates": ["water_level"]
},
"properties": {
"station_position": {
"type": "object",
"coordinateReferenceSystem": {
"reference": "http://www.opengis.net/def/crs/OGC/1.3/CRS84",
"kind": "ogc-crs",
"coordinates": ["lon", "lat"]
},
"properties": {
"lat": { "type": "double", "unit": "deg" },
"lon": { "type": "double", "unit": "deg" }
},
"required": ["lat", "lon"],
"additionalProperties": false
},
"water_level": {
"type": "double",
"unit": "m",
"examples": [2.47],
"semanticRole": "observationValue"
}
},
"required": ["station_position", "water_level"],
"additionalProperties": false
}
This specification does not define a CRS, datum, coordinate
operation, or transformation. Those definitions and semantics come
from ISO 19111 and the referenced authority.
10.2. The vectorReferenceFrames Keyword
The vectorReferenceFrames keyword identifies the reference frames on
whose axes the components of vector quantities held in properties of
an object or tuple are resolved.
A vector quantity has a magnitude and a direction, and its components
are its projections onto the axes of a frame, meaningless apart from
it. A frame is an ordered set of axis directions and has no origin,
because moving the origin does not change a vector, whereas a
Vasters Expires 7 February 2027 [Page 72]
Internet-Draft JSON Structure Semantic Annotations August 2026
coordinate reference system has one, fixed by its datum. A record
may carry both kinds of quantity: coordinateReferenceSystem binds the
members that give a position (Section 10.1), and
vectorReferenceFrames binds the members that give the components of a
vector.
A frame contributes directions only, and so does not establish the
units of the members it binds. The axes of a coordinate reference
system may carry differing units, as in a geographic system with two
angles and a height, but the components of a vector all carry the
unit of the quantity. The units of the members named by one frame
MUST be mutually convertible and SHOULD be identical.
When present, vectorReferenceFrames MUST be a non-empty array. Each
element MUST be an object with REQUIRED reference, kind, and
components, an OPTIONAL variance, and no other members. The keyword
is an array because a single record may carry more than one vector
quantity, and each quantity is resolved in its own frame.
10.2.1. The reference and kind Properties
reference and kind have the same value space and the same meaning as
in coordinateReferenceSystem (Section 10.1), under one added
condition: the axes of the referenced system MUST be directions
rather than angles, since a component is a projection onto a
direction.
A registered coordinate reference system establishes axis directions,
so it may serve as a frame wherever that condition holds. Registries
exist to identify positions, so most frames in which vectors are
reported are not registered anywhere. Such a frame is written as a
tuple meta-type whose members, in the order given by tuple, are the
axes, and whose member description values state the direction each
axis points in. The meta-type establishes the axes and their order,
not the units of the annotated members.
10.2.2. The components Property
components behaves as coordinates does. It MUST be a non-empty array
of names, and it takes one of two forms. In the first, every name is
that of a direct property of numeric type, and the names are mapped
by position onto the axes of the frame. In the second, the array
holds exactly one name, that of a direct property whose type is array
or tuple and whose elements are of numeric type, and the elements of
that property MUST supply the axes in order rather than the named
property supplying one axis. Because the components of a vector all
carry one unit, an array serves here where it would not serve for a
coordinate.
Vasters Expires 7 February 2027 [Page 73]
Internet-Draft JSON Structure Semantic Annotations August 2026
Every name in components MUST resolve to a direct property of the
annotated object or tuple. The names within one components array
MUST be distinct, since one value cannot be the component along two
axes of one frame. The number of axes supplied, whether by the names
of the first form or by the elements of the single property of the
second, MUST equal the number of axes the frame declares. The
ordering is an assertion by the schema author and is never inferred.
10.2.3. The variance Property
variance states how the components respond to a change of frame.
When present, it MUST be one of:
+===============+============================================+
| Value | Response |
+===============+============================================+
| contravariant | The components transform with the change |
| | of frame, as those of a displacement or a |
| | velocity do. |
+---------------+--------------------------------------------+
| covariant | The components transform with the inverse |
| | transpose of the change of frame, as those |
| | of a gradient or a surface normal do. |
+---------------+--------------------------------------------+
Table 18
Writing M for the matrix that carries coordinates in one frame into
coordinates in another, in the sense Section 10.4.1 fixes, a
contravariant triple v becomes M v and a covariant triple w becomes
the inverse transpose of M applied to w. The change of frame is the
passive one: the quantity does not move, the frame does.
When variance is absent, the value is contravariant. That is the
default because the quantities most often reported, among them
displacements, velocities, accelerations, and forces, are
contravariant, and the covariant ones, among them gradients and
surface normals, are the ones a schema author is likelier to be
conscious of having.
Vasters Expires 7 February 2027 [Page 74]
Internet-Draft JSON Structure Semantic Annotations August 2026
The distinction is invisible where two frames differ by a rotation
alone, because the inverse transpose of a rotation is that rotation.
It becomes visible as soon as they differ by a scaling or a shear. A
surface normal carried through a non-uniform scaling by the rule that
carries a displacement ceases to be perpendicular to the surface it
describes, and a pressure gradient carried the same way reports the
wrong rate of change. A processor that re-expresses components
without reading variance is right for rotations and wrong for
everything else, which is what this member exists to prevent.
10.2.4. Multiple Frames and Shared Components
Two elements MAY cite the same reference, which is how a record
reporting two distinct vector quantities in one frame is written. A
property MAY be named by more than one element, which asserts that
the frames share that axis and that the value is the same component
in both, and is how one quantity expressed in two frames is written.
The assertion is the schema author's, and a processor MUST NOT infer
a shared axis from a shared property, from the names of the frames,
or from equal values in samples.
Two elements that name one property MUST declare the same variance,
or omit it in both. Components of differing variance along one
shared axis agree under a rotation and part company under any other
change of frame, so one value cannot stand for both.
A property MAY also be named both by vectorReferenceFrames and by the
coordinateReferenceSystem of the same object or tuple, as a position
vector is. Where it is, the unit established by the coordinate axis
and the unit borne by the components of the vector MUST be mutually
convertible.
vectorReferenceFrames binds vector quantities and nothing else. A
rotation, a stress, a strain, or any other quantity whose components
take more than one axis index is bound by tensorReferenceFrames
(Section 10.3), since the declared order of a single frame cannot
state which axis each component belongs to. A quaternion carrying a
rotation is bound by neither keyword: three of its four members lie
along the axes of a frame and the fourth does not, so no ordered list
of components states its binding.
A reference that does not resolve leaves the frame indeterminate. It
does not make the annotation incorrect.
In the following example a satellite navigation receiver reports a
position and a velocity. EPSG:4979 fixes the position; two of its
three axes are angles, so it cannot serve as a vector frame, and the
velocity cites EPSG:4978, whose axes are geocentric X, Y, and Z. Re-
Vasters Expires 7 February 2027 [Page 75]
Internet-Draft JSON Structure Semantic Annotations August 2026
expressing the record in another system would move the position by
the whole of the transformation and would turn the velocity by its
rotation alone, which is the distinction the two keywords carry.
{
"name": "NavigationFix",
"type": "object",
"coordinateReferenceSystem": {
"reference": "http://www.opengis.net/def/crs/EPSG/0/4979",
"kind": "ogc-crs",
"coordinates": ["lat", "lon", "height"]
},
"vectorReferenceFrames": [
{
"reference": "http://www.opengis.net/def/crs/EPSG/0/4978",
"kind": "ogc-crs",
"components": ["vel_x", "vel_y", "vel_z"]
}
],
"properties": {
"lat": { "type": "double", "unit": "deg" },
"lon": { "type": "double", "unit": "deg" },
"height": { "type": "double", "unit": "m" },
"vel_x": { "type": "double", "unit": "m/s" },
"vel_y": { "type": "double", "unit": "m/s" },
"vel_z": { "type": "double", "unit": "m/s" }
},
"required": ["lat", "lon", "height", "vel_x", "vel_y", "vel_z"],
"additionalProperties": false
}
Most frames have no registered identifier. In the next example a
magnetic field is reported in two such frames, each written as a
meta-type. The frames share their first axis, so the schema reports
that component once, under bx, and names it in both elements. The
remaining components differ between the frames and are carried
separately.
{
"name": "SolarWindSample",
"type": "object",
"vectorReferenceFrames": [
{
"reference": { "$ref": "#/definitions/GseFrame" },
"kind": "type",
"components": ["bx", "by_gse", "bz_gse"]
},
{
Vasters Expires 7 February 2027 [Page 76]
Internet-Draft JSON Structure Semantic Annotations August 2026
"reference": { "$ref": "#/definitions/GsmFrame" },
"kind": "type",
"components": ["bx", "by_gsm", "bz_gsm"]
}
],
"properties": {
"bx": { "type": "double", "unit": "nT" },
"by_gse": { "type": "double", "unit": "nT" },
"bz_gse": { "type": "double", "unit": "nT" },
"by_gsm": { "type": "double", "unit": "nT" },
"bz_gsm": { "type": "double", "unit": "nT" }
},
"required": ["bx", "by_gse", "bz_gse", "by_gsm", "bz_gsm"],
"additionalProperties": false,
"definitions": {
"GseFrame": {
"name": "GseFrame",
"type": "tuple",
"description": "Geocentric Solar Ecliptic frame.",
"properties": {
"x": {
"type": "double",
"description": "Earth towards the Sun."
},
"y": {
"type": "double",
"description":
"In the ecliptic plane, towards dusk, right-handed."
},
"z": {
"type": "double",
"description":
"Parallel to the ecliptic pole, positive north."
}
},
"tuple": ["x", "y", "z"]
},
"GsmFrame": {
"name": "GsmFrame",
"type": "tuple",
"description": "Geocentric Solar Magnetospheric frame.",
"properties": {
"x": {
"type": "double",
"description": "Earth towards the Sun."
},
"y": {
"type": "double",
Vasters Expires 7 February 2027 [Page 77]
Internet-Draft JSON Structure Semantic Annotations August 2026
"description":
"Perpendicular to the dipole axis, right-handed."
},
"z": {
"type": "double",
"description":
"In the plane of x and the dipole axis, positive north."
}
},
"tuple": ["x", "y", "z"]
}
}
}
The frames are written separately because they differ, and they share
their first axis because both take x from the Earth towards the Sun.
The axis directions are those the NASA Satellite Situation Center
states for these two frames [SSC-COORDS].
This specification does not define a frame, an epoch, or a
transformation between frames. Those definitions come from the
referenced authority or from the meta-type the schema itself
supplies.
10.3. The tensorReferenceFrames Keyword
The tensorReferenceFrames keyword identifies the reference frames on
whose axes the components of tensor quantities held in properties of
an object or tuple are resolved. A tensor quantity is a grid of
numbers that means nothing without a frame to read it against. Its
rank is how many axes it takes to pick out one number of the grid:
one for a vector, two for a stress or a rotation. An engineer
checking whether a bridge beam will crack uses nine numbers because
the beam can be squeezed along its length and sheared across it at
the same time, and no single number says both.
At rank 1 the frame's declared order states the binding, which is
what vectorReferenceFrames (Section 10.2) does and why frames
requires at least two entries. Above rank 1 the vector model no
longer suffices and member names are insufficient.
vectorReferenceFrames and tensorReferenceFrames coexist, because
vectors are common and should be easy to declare.
When present, tensorReferenceFrames MUST be a non-empty array. Each
element MUST be an object with a REQUIRED frames array, a REQUIRED
components member, and an OPTIONAL symmetry string. No other members
are permitted. The keyword is an array because one record may carry
more than one tensor quantity.
Vasters Expires 7 February 2027 [Page 78]
Internet-Draft JSON Structure Semantic Annotations August 2026
10.3.1. The frames Property
frames MUST be an array of at least two objects, each with REQUIRED
reference and kind members whose values are as defined for
vectorReferenceFrames (Section 10.2). The number of entries is the
rank of the tensor, and the index in position k ranges over the axes
of the frame given by entry k, in the order that frame declares.
One frame MAY be named by more than one entry, and is so named for a
stress, a strain, or a seismic moment tensor. Where the two entries
of a rank-2 tensor name different frames, the tensor carries a vector
in the second frame to a vector in the first, as for a rotation
matrix or a Jacobian.
Each entry MAY carry variance as defined in Section 10.2.3, stating
how the index in that position responds to a change of the frame it
ranges over. The entries of one tensor need not agree. A stress
tensor is contravariant in both indices, while a Jacobian is
contravariant in the first and covariant in the second, which is what
makes it a map between frames rather than a quantity in one.
Three entries give a rank-3 tensor, and one frame may fill them all.
The piezoelectric strain coefficients of a crystal are one such
tensor: an electric field applied along one axis strains the crystal
across every pair of axes, so each coefficient is picked out by three
axes of the same crystal frame.
{
"name": "PiezoelectricCoefficients",
"type": "object",
"tensorReferenceFrames": [
{
"frames": [
{
"reference": { "$ref": "#/definitions/CrystalAxes" },
"kind": "type"
},
{
"reference": { "$ref": "#/definitions/CrystalAxes" },
"kind": "type"
},
{
"reference": { "$ref": "#/definitions/CrystalAxes" },
"kind": "type"
}
],
"components": "d"
}
Vasters Expires 7 February 2027 [Page 79]
Internet-Draft JSON Structure Semantic Annotations August 2026
],
"properties": {
"d": {
"type": "array",
"minItems": 3,
"maxItems": 3,
"items": {
"type": "array",
"minItems": 3,
"maxItems": 3,
"items": {
"type": "array",
"minItems": 3,
"maxItems": 3,
"items": { "type": "double", "ucumUnit": "C/N" }
}
}
}
},
"required": ["d"],
"additionalProperties": false,
"definitions": {
"CrystalAxes": {
"name": "CrystalAxes",
"type": "tuple",
"description": "Orthogonal frame fixed by crystal symmetry.",
"properties": {
"x1": {
"type": "double",
"description": "First axis of that frame."
},
"x2": {
"type": "double",
"description": "Second axis, at a right angle to x1."
},
"x3": {
"type": "double",
"description": "Third axis, right-handed."
}
},
"tuple": ["x1", "x2", "x3"]
}
}
}
d is nested three deep because frames has three entries, and each
level is indexed by the three axes of CrystalAxes, so it holds
twenty-seven values. The outermost index is the axis of the applied
Vasters Expires 7 February 2027 [Page 80]
Internet-Draft JSON Structure Semantic Annotations August 2026
field and the two inner ones are the axes of the strain it produces.
Each level constrains its length to three [JSTRUCT-VALIDATION], which
is how the shape the frames require is stated in the schema rather
than left to the instance.
symmetry MUST NOT be present unless frames has exactly two entries
naming the same frame and declaring the same variance, or omitting it
in both, since it speaks of an exchange of two indices ranging over
one set of axes and a pair of indices of differing variance does not
survive the exchange under a change of frame. It MUST be symmetric,
skewSymmetric, or none, and it is none where absent. Under symmetric
the component at row i and column j equals the component at row j and
column i; under skewSymmetric it is the negation of it and the
diagonal is zero. The symmetries of tensors of higher rank, such as
the minor and major symmetries of an elastic stiffness tensor, are
not expressible here, and every component of such a tensor that is
carried MUST be named individually.
10.3.2. The components Property
components MUST take one of two forms, each of which states the
pairing of index to value in the schema, and neither of which admits
a layout, packing, or multiplication convention as a separate
declaration.
The first form is a string naming a direct property of the annotated
object or tuple whose type is an array or a tuple nested to exactly
the depth given by the number of entries in frames, the outermost
level indexed by the axes of the first entry and each further level
by the next in turn, and whose innermost items are of a numeric type.
A nesting whose depth differs from the number of entries in frames
makes the annotation invalid. At every level, the number of elements
an instance carries MUST equal the number of axes declared by the
frame of the corresponding entry, so a tuple, or an array whose
length is constrained [JSTRUCT-VALIDATION], states the shape in the
schema where a bare array leaves it to the instance. The nesting
carries the layout, so the row-major and column-major question does
not arise, and a tensor declared symmetric or skewSymmetric is
written out in full in this form. Every position of the tensor is
carried, so the rule of the paragraph after the next does not apply
to this form.
The second form is a non-empty array of objects, each with a REQUIRED
index and a REQUIRED property and no other members. index MUST be an
array of non-negative integers whose length equals the number of
entries in frames, and whose integer in position k MUST be less than
the number of axes declared by the frame of entry k. property MUST
name a direct property of the annotated object or tuple having a
Vasters Expires 7 February 2027 [Page 81]
Internet-Draft JSON Structure Semantic Annotations August 2026
numeric type. Every component carried states its own index, so no
packing order is defined here and the Voigt-style orderings in
circulation need not be distinguished. Within one components array
no two entries may carry equal index values, and no two entries may
name the same property.
In the second form, a position named by no entry is determined by
symmetry where symmetry is symmetric or skewSymmetric, and is
otherwise undeclared; under none every position MUST be named. Where
symmetry is symmetric or skewSymmetric, at least one of each mirrored
pair of positions MUST be named, and where both are named the
instance values MUST stand in the relation that symmetry declares.
The units of the members named by one element MUST be mutually
convertible and SHOULD be identical.
The Global CMT catalogue publishes a source solution for every
significant earthquake as a fixed-column text record, and states the
frame those solutions are resolved on only in the document describing
that format: six moment-tensor elements against a spherical frame in
which r is up, t is south, and p is east [GCMT-NDK]. The tensor is
symmetric, so those six determine all nine, and the second form of
components states the index of each without appeal to a packing
order. What a reader of the text file must look up, the schema
carries.
{
"name": "MomentTensor",
"type": "object",
"tensorReferenceFrames": [
{
"frames": [
{
"reference": { "$ref": "#/definitions/UseFrame" },
"kind": "type"
},
{
"reference": { "$ref": "#/definitions/UseFrame" },
"kind": "type"
}
],
"symmetry": "symmetric",
"components": [
{ "index": [0, 0], "property": "mrr" },
{ "index": [1, 1], "property": "mtt" },
{ "index": [2, 2], "property": "mpp" },
{ "index": [0, 1], "property": "mrt" },
{ "index": [0, 2], "property": "mrp" },
{ "index": [1, 2], "property": "mtp" }
Vasters Expires 7 February 2027 [Page 82]
Internet-Draft JSON Structure Semantic Annotations August 2026
]
}
],
"coordinateReferenceSystem": {
"reference": "http://www.opengis.net/def/crs/EPSG/0/4326",
"kind": "ogc-crs",
"coordinates": ["lat", "lon"]
},
"properties": {
"eventName": { "type": "string" },
"centroidTime": { "type": "datetime" },
"lat": { "type": "double", "unit": "deg" },
"lon": { "type": "double", "unit": "deg" },
"depth": { "type": "double", "ucumUnit": "km" },
"mrr": { "type": "double", "ucumUnit": "dyn.cm" },
"mtt": { "type": "double", "ucumUnit": "dyn.cm" },
"mpp": { "type": "double", "ucumUnit": "dyn.cm" },
"mrt": { "type": "double", "ucumUnit": "dyn.cm" },
"mrp": { "type": "double", "ucumUnit": "dyn.cm" },
"mtp": { "type": "double", "ucumUnit": "dyn.cm" }
},
"required": [
"eventName", "centroidTime", "lat", "lon", "depth",
"mrr", "mtt", "mpp", "mrt", "mrp", "mtp"
],
"additionalProperties": false,
"definitions": {
"UseFrame": {
"name": "UseFrame",
"type": "tuple",
"description":
"Spherical frame of the Global CMT catalogue, at lat/lon.",
"properties": {
"r": { "type": "double", "description": "Up." },
"t": { "type": "double", "description": "South." },
"p": { "type": "double", "description": "East." }
},
"tuple": ["r", "t", "p"]
}
}
}
The following is the sample record printed in that same document: an
earthquake beneath El Salvador on 1 January 2005, whose six elements
give the orientation and the size of the movement on the fault, in
dyne-centimetres. The catalogue prints them scaled by a power of ten
carried on a line of its own, and the instance carries the values
themselves, that is, with the exponent applied.
Vasters Expires 7 February 2027 [Page 83]
Internet-Draft JSON Structure Semantic Annotations August 2026
{
"eventName": "C200501010120A",
"centroidTime": "2005-01-01T01:20:05.1Z",
"lat": 13.76,
"lon": -89.08,
"depth": 162.8,
"mrr": 0.838e23,
"mtt": -0.005e23,
"mpp": -0.833e23,
"mrt": 1.050e23,
"mrp": -0.369e23,
"mtp": 0.044e23
}
The value under mtp sits at row 1 and column 2, and the declaration
of symmetric puts the same value at row 2 and column 1. Nothing in
the instance says so: the six numbers alone determine nine components
only once the schema has stated the frame, the index of each, and the
symmetry.
UseFrame is a local frame, and up, south, and east are directions
only once a point on the Earth is given. The point is the one the
coordinateReferenceSystem of the same object binds, and the
description of the meta-type is where a schema says so. This
document defines no member that binds a frame to the position that
orients it, and a processor MUST NOT infer such a binding from the
presence of both keywords on one type.
A rank-2 quantity whose two entries name different frames is a map
from one frame to the other, and an attitude matrix, a Jacobian, and
a sensor alignment are all of that shape. tensorReferenceFrames
describes such a quantity correctly, but it says only what the
indices range over. It does not say that the numbers are a
transformation, and it cannot describe the quaternion, the axis and
angle, or the three Euler angles that the same transformation is more
often published as. Where the annotated properties carry a
transformation, frameTransforms (Section 10.4) SHOULD be used
instead.
10.4. The frameTransforms Keyword
The frameTransforms keyword identifies properties of an object or
tuple that carry a transformation from one reference frame to
another.
The keywords before it bind quantities. coordinateReferenceSystem
binds a position, vectorReferenceFrames binds a direction, and
tensorReferenceFrames binds a quantity whose components take more
Vasters Expires 7 February 2027 [Page 84]
Internet-Draft JSON Structure Semantic Annotations August 2026
than one axis index. A transformation is none of those. It is the
map between two frames, and the numbers carrying it mean nothing
until the sense of the map, the handedness of its angles, and the
arrangement of its components are all settled.
Common practice settles none of them. NASA's Navigation and
Ancillary Information Facility, which maintains the toolkit most
planetary missions navigate with, states the position plainly: "there
are no standards defining construction of quaternions, the underlying
associated mathematics, or the connection to rotations. In the
absence of such standards, different organizations adopt disparate
definitions, which makes communication difficult" [NAIF-QUAT]. The
same paper enumerates what a reader must resolve before a rotation
can be applied: whether a positive angle turns in the right-hand
sense, whether the rotation turns a vector or turns the frame,
whether the matrix multiplies from the left or the right, whether the
sense runs from the base frame or towards it, and, for a quaternion,
where the scalar sits and what sign its multiplication rule carries.
Six independent choices, of which, as that paper observes, "the
composition of several misunderstandings can lead to correct results
in one context, incorrect in another, and frustration in general".
The Robot Operating System reaches the same conclusion about Euler
angles, which it discourages "due to having 24 'valid' conventions
with different domains using different conventions by default"
[REP-103].
When present, frameTransforms MUST be a non-empty array. Each
element MUST be an object with REQUIRED from, to, encoding, and
components, OPTIONAL rotationSequence and translation, and no other
members. The keyword is an array because one record may carry more
than one transformation, as an attitude message does when it gives
the orientation of a single instrument against two different
reference frames.
10.4.1. The Conventions This Document Fixes
Every frame named by from or to MUST be right-handed and MUST declare
exactly three axes, and a positive angle MUST be read as a rotation
in the right-hand sense about the axis it is stated against. Every
encoding this keyword defines presupposes three dimensions, so a
frame of any other arity cannot be named by either member.
Vasters Expires 7 February 2027 [Page 85]
Internet-Draft JSON Structure Semantic Annotations August 2026
A transformation carries coordinates expressed in the from frame into
coordinates expressed in the to frame. Writing x for the coordinates
of a vector in the from frame and x' for the coordinates of the same
vector in the to frame, the transformation is the M for which x' = M
x, and translation, where present, adds to that as x' = M x + t.
This is the frame-transformation sense rather than the vector-
rotation sense: the quantity does not move, the frame does.
The Consultative Committee for Space Data Systems states that same
sense for its attitude messages. The quaternion "from frame A to
frame B" is "the quaternion of the rotation that transforms the basis
vectors of frame A into the basis vectors of frame B", and the matrix
it corresponds to is defined by XB = MBA * XA [CCSDS-ADM].
This document fixes these choices rather than offering them as
members to be declared, and that committee is the precedent. Its
first issue made both the direction and the placement of the
quaternion scalar into fields a producer filled in, ATTITUDE_DIR
taking A2B or B2A and QUATERNION_TYPE taking FIRST or LAST
[CCSDS-ADM1]. Its second issue deleted both, recording the rationale
as "Simplicity of the standard" and, for the wider set of changes
that pinned the meanings down, "To avoid misuse of exchange data"
[CCSDS-ADM]. Fixing them cost that standard the ability to carry
records laid out the other way, because its records are positional.
It costs this document nothing, because components names members
rather than positions. A schema whose quaternion is stored scalar-
last and one whose quaternion is stored scalar-first carry the same
annotation, with the names written in the order fixed here.
10.4.2. The from and to Properties
from and to MUST each be an object with a REQUIRED reference and a
REQUIRED kind, whose value spaces and meanings are those they have in
vectorReferenceFrames (Section 10.2). The axes of both frames MUST
be directions rather than angles. variance MUST NOT appear in either,
since a frame named by a transformation is not an index position of a
quantity.
from and to MAY cite the same reference. A transformation between
two realizations of one frame, or between one frame at two epochs, is
written that way.
10.4.3. The encoding Property
encoding states which arrangement of numbers carries the
transformation. It is a closed enumeration, and a value outside it
is invalid, because each value carries an arithmetic meaning that
this document defines.
Vasters Expires 7 February 2027 [Page 86]
Internet-Draft JSON Structure Semantic Annotations August 2026
+===================+========================================+
| Encoding | Carried by |
+===================+========================================+
| quaternion | Four members: the scalar, then the |
| | three components of the vector part. |
+-------------------+----------------------------------------+
| axisAngle | Four members: the angle, then the |
| | three components of the rotation axis. |
+-------------------+----------------------------------------+
| eulerAngles | Three members: the angles of three |
| | successive intrinsic rotations. |
+-------------------+----------------------------------------+
| rotationMatrix | Nine values arranged three by three. |
+-------------------+----------------------------------------+
| homogeneousMatrix | Sixteen values arranged four by four, |
| | acting on augmented coordinates. |
+-------------------+----------------------------------------+
Table 19
Every encoding but the last carries a rotation and nothing else, and
an offset between the origins of the two frames is then carried by
translation (Section 10.4.6) or not at all. homogeneousMatrix carries
the rotation and the offset together in one matrix M4, acting on
augmented coordinates as [x', 1] = M4 [x, 1] written as column
vectors. Its first three rows and first three columns are the
rotation M, its fourth column holds in its first three entries the
same three values translation would carry and in its fourth entry a
one, and its fourth row is three zeroes and a one.
The nine values of a rotationMatrix, and the first three rows and
columns of a homogeneousMatrix, SHOULD be orthonormal with
determinant positive one, within a tolerance appropriate to the
numeric type. A processor is not required to verify this, and this
document defines no tolerance. The remaining entries of a
homogeneousMatrix MUST be as the previous paragraph states, so a
projective matrix, a matrix carrying a scaling or a shear, and a
matrix whose fourth row is anything other than three zeroes and a one
are all outside this encoding.
Vasters Expires 7 February 2027 [Page 87]
Internet-Draft JSON Structure Semantic Annotations August 2026
The first three entries of the fourth column of a homogeneousMatrix
carry a length and the rest of the matrix is dimensionless, so those
three entries are subject to the same unit rule as translation
(Section 10.4.6): their units MUST be mutually convertible and SHOULD
be identical. A single nested property cannot state a unit for one
position and not another, so a schema carrying a homogeneousMatrix in
that form MUST establish those units in the referenced definition or
in the indexed form of components, which names a separate property
for each position.
10.4.4. The components Property
components names the members that carry the transformation, and its
form follows encoding.
For quaternion, axisAngle, and eulerAngles, components MUST be an
array of names of direct properties of the annotated object or tuple,
all of numeric type and all distinct, of the length the encoding
requires. Order within that array is fixed by this document. It is
never inferred from the order in which the properties are declared,
from their names, or from their position in a tuple.
For rotationMatrix and homogeneousMatrix, components MUST be either
the name of one property whose type is an array or a tuple nested
twice, the outer index selecting the row, or an array of indexed
components in the form tensorReferenceFrames uses (Section 10.3),
each stating its own index of two non-negative integers, row first.
Neither form leaves a row-major or column-major reading open, which a
flat array of nine or sixteen values would.
In the nested form, each instance level MUST carry three elements for
rotationMatrix and four for homogeneousMatrix. In the indexed form,
every position MUST be named, nine of them for rotationMatrix and
sixteen for homogeneousMatrix, and each integer of an index MUST be
less than three, respectively four. symmetry has no counterpart here,
so no position is determined by any other and none may be left
undeclared.
10.4.4.1. Quaternions
The four names given for quaternion are, in order, the member
carrying the scalar and the members carrying the three components of
the vector part, in the axis order the frames declare. Writing a for
the angle of the rotation that carries the from frame into the to
frame and e for its unit axis, the scalar is cos(a/2) and each of the
other three is sin(a/2) times the corresponding component of e. The
axis is unchanged by its own rotation, so its components are the same
in both frames and the question of which frame they are resolved in
Vasters Expires 7 February 2027 [Page 88]
Internet-Draft JSON Structure Semantic Annotations August 2026
does not arise. Which physical direction the second, third, and
fourth names stand for therefore follows from the axis order the
frames declare, not from any convention of this document.
The four values taken together SHOULD have unit norm, and the scalar
SHOULD be non-negative, which confines the rotation angle to a half
turn either way [CCSDS-ADM1].
A worked case fixes the sense. Let the to frame be the from frame
turned a quarter turn in the right-hand sense about the third axis,
so that the first axis of the to frame has the coordinates 0, 1, 0 in
the from frame. The quaternion is then the scalar 0.7071 with axis
components 0, 0, 0.7071, and a vector whose coordinates in the from
frame are 1, 0, 0 has the coordinates 0, -1, 0 in the to frame.
Those are the values [CCSDS-ADM] prints for the same case.
One other convention is in wide enough use to name. The SPICE
toolkit places the scalar first, as this document does, and measures
its angle as the rotation of the coordinate system from the base
frame in the right-hand sense, as this document does. It
nevertheless carries the negation of the vector part this document
carries, so for the case above it gives the scalar 0.7071 with vector
components 0, 0, -0.7071. The cause is not the parameterization but
the multiplication rule: NAIF records that its own product takes the
cross-product term positive where the other convention in circulation
takes it negative, that this "has the effect of inverting the sense
of the rotation", and that converting a quaternion of the other
convention into a SPICE one is done by moving the scalar to the front
and negating the remaining three [NAIF-QUAT]. The two therefore
differ in the sign of the vector part while agreeing on everything a
reader is likely to check, and nothing in the four numbers reveals
which was meant. That is the ambiguity this keyword removes.
The example below annotates an attitude carried as four separate
properties. The record stores the scalar last, as the current
attitude message standard requires of its own records, and components
names it first, as this document requires of the annotation.
{
"name": "SpacecraftAttitude",
"type": "object",
"frameTransforms": [
{
"from": {
"reference": { "$ref": "#/definitions/BodyFrame" },
"kind": "type"
},
"to": {
Vasters Expires 7 February 2027 [Page 89]
Internet-Draft JSON Structure Semantic Annotations August 2026
"reference": "http://www.opengis.net/def/crs/EPSG/0/4978",
"kind": "ogc-crs"
},
"encoding": "quaternion",
"components": ["qc", "q1", "q2", "q3"]
}
],
"properties": {
"epoch": { "type": "datetime" },
"q1": { "type": "double" },
"q2": { "type": "double" },
"q3": { "type": "double" },
"qc": { "type": "double" }
},
"required": ["epoch", "q1", "q2", "q3", "qc"],
"additionalProperties": false,
"definitions": {
"BodyFrame": {
"name": "BodyFrame",
"type": "tuple",
"description": "Spacecraft body frame.",
"properties": {
"x": {
"type": "double",
"description": "Along the instrument boresight."
},
"y": {
"type": "double",
"description": "Completes a right-handed set."
},
"z": {
"type": "double",
"description": "Towards the solar array hinge."
}
},
"tuple": ["x", "y", "z"]
}
}
}
An instance carrying the quarter turn worked above is the following.
Vasters Expires 7 February 2027 [Page 90]
Internet-Draft JSON Structure Semantic Annotations August 2026
{
"epoch": "2003-09-30T14:28:15.1172Z",
"q1": 0.0,
"q2": 0.0,
"q3": 0.7071068,
"qc": 0.7071068
}
10.4.4.2. Axis and Angle
The four names given for axisAngle are, in order, the member carrying
the angle and the members carrying the three components of the axis.
The angle is that of the rotation carrying the from frame into the to
frame, measured in the right-hand sense about the axis, and the axis
components SHOULD have unit norm. This is the one rotation-only
encoding whose members do not all carry one unit: the angle MUST
carry a unit or ucumUnit annotation of angle through [JSTRUCT-UNITS],
since radians and degrees are not distinguishable in the value, and
the axis components carry none. homogeneousMatrix likewise mixes
units, its rotation entries carrying none and its offset entries
carrying a length.
10.4.4.3. Euler Angles
eulerAngles requires rotationSequence, and the three names in
components are the angles of the first, second, and third rotation in
the order that sequence gives.
The rotations are intrinsic. The first turns the from frame about
the axis the first letter names, the second turns the frame the first
produced about the axis the second letter names, and the third turns
the frame the second produced, the result being the to frame. Under
the extrinsic reading, where every rotation is about an axis of the
original frame, the same three angles against the same sequence
describe a different transformation. Nothing is lost by fixing the
intrinsic reading, because every extrinsic sequence has an intrinsic
equal that Section 10.4.5 gives; degenerate cases, such as all three
angles being zero, agree under both readings and need no conversion.
That this needs saying is shown by the standard that most needs it.
The current attitude message standard states the composition is
intrinsic exactly once, in an annex marked informative [CCSDS-ADM],
and the issue that preceded it for sixteen years never stated it at
all [CCSDS-ADM1].
Vasters Expires 7 February 2027 [Page 91]
Internet-Draft JSON Structure Semantic Annotations August 2026
10.4.5. The rotationSequence Property
rotationSequence MUST be present when encoding is eulerAngles and
MUST NOT be present otherwise. Its value MUST be three characters
drawn from X, Y, and Z, no two adjacent characters being equal, which
admits twelve values: XYX, XYZ, XZX, XZY, YXY, YXZ, YZX, YZY, ZXY,
ZXZ, ZYX, and ZYZ. The value is case-sensitive, and only these
twelve upper-case strings are valid. The leftmost character names
the axis of the first rotation.
X names the first axis of the frame being turned, Y the second, and Z
the third, in the order that frame declares its axes. The letters
are positional and carry no direction of their own, whatever the
frame calls its axes: in a frame declaring north, east, and down, X
is north, Y is east, and Z is down.
Twelve values are enough for every rotation, including every rotation
a source states extrinsically, and an annotator working from such a
source converts rather than looks for a value that is not there. A
rotation stated extrinsically as a sequence of three axes with three
angles is the same rotation as the intrinsic sequence whose axis
letters are those three in reverse, taking the same three angle
values in reverse order. Both reverse. Reversing the letters while
leaving the angles in place, or the reverse of that, gives a
different rotation, and is the error this paragraph exists to
prevent.
The twelve conversions are these. In every row the angles reverse,
so components names the member holding the source's third angle first
and the member holding its first angle last.
Vasters Expires 7 February 2027 [Page 92]
Internet-Draft JSON Structure Semantic Annotations August 2026
+====================+========================+==================+
| Extrinsic sequence | rotationSequence value | components order |
+====================+========================+==================+
| XYX | XYX | third, second, |
| | | first |
+--------------------+------------------------+------------------+
| XYZ | ZYX | third, second, |
| | | first |
+--------------------+------------------------+------------------+
| XZX | XZX | third, second, |
| | | first |
+--------------------+------------------------+------------------+
| XZY | YZX | third, second, |
| | | first |
+--------------------+------------------------+------------------+
| YXY | YXY | third, second, |
| | | first |
+--------------------+------------------------+------------------+
| YXZ | ZXY | third, second, |
| | | first |
+--------------------+------------------------+------------------+
| YZX | XZY | third, second, |
| | | first |
+--------------------+------------------------+------------------+
| YZY | YZY | third, second, |
| | | first |
+--------------------+------------------------+------------------+
| ZXY | YXZ | third, second, |
| | | first |
+--------------------+------------------------+------------------+
| ZXZ | ZXZ | third, second, |
| | | first |
+--------------------+------------------------+------------------+
| ZYX | XYZ | third, second, |
| | | first |
+--------------------+------------------------+------------------+
| ZYZ | ZYZ | third, second, |
| | | first |
+--------------------+------------------------+------------------+
Table 20
Vasters Expires 7 February 2027 [Page 93]
Internet-Draft JSON Structure Semantic Annotations August 2026
The six sequences whose first and third letters are equal reverse to
themselves, and those rows are the ones to read carefully: the value
written is the same string the source gives, which makes it easy to
conclude that nothing needs doing. Something does. The angles still
reverse, and an extrinsic ZXZ recorded as an intrinsic ZXZ with the
angles left in source order is a different rotation from the one the
source states.
A source giving an extrinsic X-then-Y-then-Z rotation of 10, 20, and
30 degrees is therefore annotated with a rotationSequence of ZYX, and
components naming the member holding 30 degrees first, then the
member holding 20, then the member holding 10. The members
themselves do not move and their values are not rewritten; only the
order in which components names them changes. Because nothing in the
annotation records that the source was extrinsic, a schema that
converts SHOULD say so in description, so that a later reader
comparing the schema against the source document does not read the
reversal as a mistake. An extrinsic reading MUST NOT be recorded by
inventing a thirteenth value, a lower-case spelling, or any other
marking.
The six values whose first and third characters are equal are
permitted, though the standard that first enumerated them discouraged
them "as their use can cause confusion" [CCSDS-ADM1].
10.4.6. The translation Property
translation, when present, MUST be an array of exactly three names of
direct properties of the annotated object or tuple, all of numeric
type and all distinct, giving the coordinates of the origin of the
from frame expressed in the to frame, on the axes of the to frame in
the order that frame declares them. That is the t of x' = M x + t
(Section 10.4.1), and it is the offset from the origin of the to
frame to the origin of the from frame, not the other way about.
Their units MUST be mutually convertible and SHOULD be identical.
translation MUST NOT be present when encoding is homogeneousMatrix,
whose fourth column carries the same three values in the same sense.
Where translation is absent and encoding is not homogeneousMatrix,
the element declares a rotation and says nothing about the origins,
which is the correct reading for an attitude and the wrong one for a
sensor alignment.
The KITTI dataset publishes the alignment between its laser scanner
and its reference camera in a calibration file holding nine numbers
on one line and three on another, and states in its paper that the
rotation and the translation run from the laser to the camera
[KITTI]. Neither the file nor the paper says whether the nine
Vasters Expires 7 February 2027 [Page 94]
Internet-Draft JSON Structure Semantic Annotations August 2026
numbers are rows or columns; the developer kit for one of its
benchmarks states that its matrices are stored row-major, and the raw
calibration file carries no such statement. The two readings are
transposes of one another, and for a rotation matrix both are valid
rotations, so nothing in the numbers rules either out. Only the
physical arrangement of the sensors does. The schema below states
the reading, and the axis directions the file leaves to the reader,
as declarations.
{
"name": "SensorAlignment",
"type": "object",
"frameTransforms": [
{
"from": {
"reference": { "$ref": "#/definitions/LaserFrame" },
"kind": "type"
},
"to": {
"reference": { "$ref": "#/definitions/CameraFrame" },
"kind": "type"
},
"encoding": "rotationMatrix",
"components": "rotation",
"translation": ["tx", "ty", "tz"]
}
],
"properties": {
"calibrationTime": { "type": "datetime" },
"rotation": {
"type": "array",
"minItems": 3,
"maxItems": 3,
"items": {
"type": "array",
"minItems": 3,
"maxItems": 3,
"items": { "type": "double" }
}
},
"tx": { "type": "double", "ucumUnit": "m" },
"ty": { "type": "double", "ucumUnit": "m" },
"tz": { "type": "double", "ucumUnit": "m" }
},
"required": ["calibrationTime", "rotation", "tx", "ty", "tz"],
"additionalProperties": false,
"definitions": {
"LaserFrame": {
Vasters Expires 7 February 2027 [Page 95]
Internet-Draft JSON Structure Semantic Annotations August 2026
"name": "LaserFrame",
"type": "tuple",
"description": "Frame of the rotating laser scanner.",
"properties": {
"x": {
"type": "double",
"description": "Forward along the vehicle."
},
"y": {
"type": "double",
"description": "To the left of the vehicle."
},
"z": { "type": "double", "description": "Up." }
},
"tuple": ["x", "y", "z"]
},
"CameraFrame": {
"name": "CameraFrame",
"type": "tuple",
"description": "Frame of the reference camera.",
"properties": {
"x": {
"type": "double",
"description": "To the right in the image."
},
"y": {
"type": "double",
"description": "Down in the image."
},
"z": {
"type": "double",
"description": "Along the optical axis, from the camera."
}
},
"tuple": ["x", "y", "z"]
}
}
}
The instance below carries the values that dataset publishes for one
recording day.
Vasters Expires 7 February 2027 [Page 96]
Internet-Draft JSON Structure Semantic Annotations August 2026
{
"calibrationTime": "2012-03-15T11:37:16Z",
"rotation": [
[0.007533745, -0.9999714, -0.000616602],
[0.01480249, 0.0007280733, -0.9998902],
[0.9998621, 0.00752379, 0.01480755]
],
"tx": -0.004069766,
"ty": -0.07631618,
"tz": -0.2717806
}
Read as rows, the first inner array gives the first axis of the
camera frame in the components of the laser frame, and the matrix
maps the forward axis of the laser onto the optical axis of the
camera, which is the arrangement the vehicle has. Read as columns,
it maps them the other way. The file name carries the direction and
nothing carries the layout, which is the division of labor this
keyword ends.
10.5. The linearReferenceSystem Keyword
The linearReferenceSystem keyword identifies the linear reference
system [ISO19148] under which a location held in properties of an
object or tuple is to be interpreted.
When present, linearReferenceSystem MUST be an object with REQUIRED
reference, kind, linearElement, and measure strings and OPTIONAL
measureEnd and direction strings. No other properties are permitted.
10.5.1. The reference Property
reference MUST identify one linear reference system. Where kind is
type it MUST be a type reference { "$ref": <JSON Pointer> }
[JSTRUCT-CORE] to a shareable type definition, and otherwise it MUST
be an absolute URI [RFC3986]. The identified definition MUST
establish the linear referencing method, the measure origin, the
increasing-measure direction, the measure unit, and the linear-
element namespace. kind states which definition model the reference
identifies.
A processor is not required to dereference the URI. This document
does not define a resolution protocol, URI layout, storage model, or
definition serialization.
Vasters Expires 7 February 2027 [Page 97]
Internet-Draft JSON Structure Semantic Annotations August 2026
10.5.2. The kind Property
kind classifies which definition model the URI identifies. It is an
open enumeration. The following values are defined here:
+=============+===================================================+
| Kind | Referenced definition |
+=============+===================================================+
| lrs-network | A network published by a geospatial feature |
| | service whose layer and metadata resources |
| | establish the linear elements and the measure, |
| | such as the WSDOT State Route system [WSDOT-LRS]. |
+-------------+---------------------------------------------------+
| type | A meta-type declaring members whose referenceRole |
| | is linearElement and measure, and optionally |
| | direction (Section 8). |
+-------------+---------------------------------------------------+
Table 21
Other values MAY name further definition models. Appendix A
discusses the availability of registered definitions.
Since the identified definition MUST establish the measure unit, the
increasing-measure direction, and the linear-element namespace, a
feature service layer that carries measure values on its vertices and
a route identifier field without stating those is a rendering of
positions in a reference system rather than a definition of one, and
it does not qualify as an lrs-network.
A type reference carries a system that no authority publishes, such
as one internal to a plant, a terminal, or a private network. The
referenced meta-type MUST declare a member whose referenceRole is
linearElement and a member whose referenceRole is measure, and MAY
declare one whose referenceRole is direction. The linearElement,
measure, and direction properties of the annotation map the annotated
properties onto those members, so the type of the element identifier
and the unit of the measure are checkable. Where the annotation
names a measureEnd, that property maps onto the same member of the
meta-type as measure, because both carry a distance in the same
system. The referencing method, measure origin, increasing-measure
direction, and linear-element namespace are stated in the description
of the meta-type or of its members.
Vasters Expires 7 February 2027 [Page 98]
Internet-Draft JSON Structure Semantic Annotations August 2026
10.5.3. The linearElement Property
linearElement MUST name a direct property of the annotated object or
tuple. The property value identifies the road, railway, waterway,
route, or other linear element within the linear-element namespace
established by the identified system.
10.5.4. The measure Property
measure MUST name a direct numeric property, distinct from
linearElement. The property gives the distance from the measure
origin along the identified linear element. It MUST have a unit or
ucumUnit annotation compatible with the measure unit established by
the identified system.
10.5.5. The measureEnd Property
measureEnd, when present, MUST name another distinct direct numeric
property whose type and unit are those required of measure.
Where measureEnd is absent, the annotation locates a point on the
linear element at measure. Where it is present, the annotation
locates the span of that element between measure and measureEnd, and
measure is the start of the span. Both ends lie on the one element
that linearElement identifies, and this document defines no span
crossing two elements.
The span is closed at both ends, which differs from the half-open
convention this document uses for temporal intervals. Two spans that
share an end therefore share the point at that end, and a consumer
counting over abutting sections MUST account for that shared point.
A span whose ends are equal is the point at that measure. This
document does not require that measureEnd exceed measure, since a
system whose increasing-measure direction opposes the direction of
travel encodes a forward span with a decreasing pair.
10.5.6. The direction Property
direction, when present, MUST name another distinct direct property.
Its value qualifies the direction of travel or orientation using the
vocabulary established by the identified system. It does not alter
the increasing-measure direction.
Properties not named by linearElement, measure, measureEnd, or
direction are not part of the linearly referenced location.
Vasters Expires 7 February 2027 [Page 99]
Internet-Draft JSON Structure Semantic Annotations August 2026
This binding describes a location along one identified linear
element, either a point or a span. This document does not define
offsets, referent-relative addressing, interpolative methods,
transformations between linear reference systems, or network
topology.
The following excerpt locates a point on a Washington State route,
where arm is the accumulated route mile measured from the route
origin. The cited service qualifies as an lrs-network because the
layer it names publishes the route identifier syntax and the
increasing-measure direction in its own metadata rather than leaving
them to a reader of the geometry: it decomposes the route identifier
into its parts and states that "a directional indicator has been
added to the RouteIdentifier to distinguish between the increasing
and decreasing direction of mileposting" [WSDOT-LRS]. It does not
state the unit of the measure values, which is why the measure rule
requires the annotated property to carry one:
========== NOTE: '\' line wrapping per RFC 8792 ===========
{
"name": "WsdotStateRouteLocation",
"type": "object",
"linearReferenceSystem": {
"reference": "https://data.wsdot.wa.gov/arcgis/rest/services/\
Shared/LRSData/FeatureServer/9",
"kind": "lrs-network",
"linearElement": "route_identifier",
"measure": "arm",
"direction": "inventory_direction"
},
"properties": {
"route_identifier": {
"type": "string"
},
"arm": {
"type": "double",
"unit": "mi",
"ucumUnit": "[mi_i]"
},
"inventory_direction": {
"type": "string"
}
},
"required": ["route_identifier", "arm", "inventory_direction"],
"additionalProperties": false
}
Vasters Expires 7 February 2027 [Page 100]
Internet-Draft JSON Structure Semantic Annotations August 2026
11. Colorimetric Reference Annotations
Color is the worked instance of a larger family: components resolved
onto the channels of a named space, where the space fixes the basis
those numbers weigh, the reference they stand relative to, and the
encoding they carry. Section 10 gives that treatment to positions
and directions, and this section gives it to color, because color is
the perceptual signal most often carried in general-purpose JSON —
design tokens, stylesheets, image metadata — and the one most often
carried with all of that left silent. The same family continues past
color in Section 12, where audio channel layout and multiband imaging
resolve channel numbers onto a named space as color does. A coded
value bound to an external list (Section 6) and the weighting a
scalar measurement carries (Section 7) are relatives of a different
shape, each treated in its own section.
11.1. The colorSpaces Keyword
The colorSpaces keyword identifies the color spaces in which channel
values held in properties of an object or tuple are to be
interpreted.
A color value is a measurement. Three numbers are not a color until
something states which primaries they weigh, what white they are
relative to, what range they run over, and whether they are
proportional to light or to the signal that drives a display. Most
of those are almost never carried with the numbers, and the ones that
are are carried by conventions that differ between formats.
The keywords of Section 10 lean on registers. A position has the
EPSG dataset and the OGC definitions server behind it, and a schema
names a system by a URI that resolves to a definition of it. Color
has no equivalent. The International Color Consortium publishes
registries of RGB color spaces and of print characterization data,
but those are pages written for a reader rather than identifiers
minted for a machine [ICC-REGISTRY]. What exists in place of a
register is of two other sorts. A standards document may assign a
code point, as [ITU-H273] assigns combinations of primaries, transfer
function, matrix coefficients, and signal range to four integers. Or
the definition travels with the data as a profile, identified by a
checksum over its own contents [ICC-SPEC]. Neither is a URI and
neither dereferences. A reference in this keyword identifies more
often than it resolves, which is true of the other reference-style
keywords as well but is true of this one always.
When present, colorSpaces MUST be a non-empty array. Each element
MUST be an object with REQUIRED reference, kind, and channels,
OPTIONAL codePoints, packing, alpha, alphaMode, transfer, illuminant,
Vasters Expires 7 February 2027 [Page 101]
Internet-Draft JSON Structure Semantic Annotations August 2026
and observer, and no other members. The keyword is an array because
one record may carry a color in more than one space, as a
characterization dataset does when it gives the device values that
were printed alongside the color that was measured off the result.
These members can disagree, and one principle settles every case in
which they do. reference identifies a definition that describes a
class of data, while codePoints, transfer, illuminant, and observer
state what is true of _this_ data. The narrower statement prevails,
because a schema author declaring one is recording a fact about the
values in hand and a definition cannot be. The specific rules follow
from that and are stated where each member is defined
(Section 11.1.2, Section 11.1.6, Section 11.1.7); no rule lets a
definition override a member, and none of them makes a schema
invalid, since a processor that cannot resolve the definition cannot
detect the disagreement in the first place.
11.1.1. The reference and kind Properties
reference MUST identify one color space or one set of device control
values. Where kind is type it MUST be a type reference { "$ref":
<JSON Pointer> } [JSTRUCT-CORE] to a shareable type definition.
Where kind is icc-profile it MUST be a URI [RFC3986] identifying the
profile; the profile identifier [ICC-SPEC] computes over the profile
contents is not itself a URI, and a schema carrying only that
identifier MUST express it as one, under a scheme of the schema
author's choosing that states which digest the remainder is.
Otherwise it MUST be an absolute URI [RFC3986].
What the identified definition MUST establish follows from what is
being identified.
Vasters Expires 7 February 2027 [Page 102]
Internet-Draft JSON Structure Semantic Annotations August 2026
+========================+=========================================+
| Identified | What the definition establishes |
+========================+=========================================+
| A space whose channels | The primaries, the white point, and the |
| are additive primaries | transfer function. |
+------------------------+-----------------------------------------+
| A space whose channels | The reference white, and the illuminant |
| are tristimulus | and the standard colorimetric observer, |
| quantities, or are | or else the schema declares them under |
| computed from them | illuminant and observer. |
+------------------------+-----------------------------------------+
| A set of device | The device, medium, and process the |
| control values | values drive, and the measurement |
| | conditions under which the result was |
| | characterized. |
+------------------------+-----------------------------------------+
Table 22
A set of device control values is not a color space in the
colorimetric sense, and the third row exists because such values are
carried alongside colors often enough that excluding them would push
the commonest characterization record out of this keyword. channels,
alpha, and alphaMode apply to it unchanged; codePoints, transfer,
illuminant, and observer do not, and MUST NOT be present on an
element identifying one.
kind classifies which definition model the reference identifies. It
is an open enumeration. The following values are defined here:
Vasters Expires 7 February 2027 [Page 103]
Internet-Draft JSON Structure Semantic Annotations August 2026
+==============+============================================+
| Kind | Referenced definition |
+==============+============================================+
| itu | A Recommendation of the International |
| | Telecommunication Union. |
+--------------+--------------------------------------------+
| iec | A standard of the International |
| | Electrotechnical Commission. |
+--------------+--------------------------------------------+
| cie | A publication of the International |
| | Commission on Illumination [CIE015]. |
+--------------+--------------------------------------------+
| icc-profile | An ICC profile, identified as [ICC-SPEC] |
| | identifies one. |
+--------------+--------------------------------------------+
| icc-registry | An entry in a registry the International |
| | Color Consortium publishes [ICC-REGISTRY]. |
+--------------+--------------------------------------------+
| type | A meta-type in the annotated schema, as |
| | Section 8 describes. |
+--------------+--------------------------------------------+
Table 23
A processor is not required to dereference the URI. This document
does not define a resolution protocol, URI layout, storage model, or
definition serialization. Where an element carries codePoints,
transfer, illuminant, or observer alongside reference, those members
prevail over the identified definition where the two disagree
(Section 11.1.2, Section 11.1.6, Section 11.1.7).
11.1.2. The codePoints Property
codePoints, when present, MUST be an array of exactly four non-
negative integers, being the color primaries, transfer
characteristics, matrix coefficients, and video full range flag that
[ITU-H273] defines, in that order.
These four integers are the only identifier of a color space that is
both machine-readable and widely deployed. The PNG specification
carries the same four in a chunk of its own, gives that chunk
precedence over every other color declaration a file may hold, and
requires the chunk carrying mastering display metadata to be
accompanied by it, on the ground that such metadata means nothing
without the space it is relative to [PNG3]. Where the identified
definition and the code points disagree, the code points are the
narrower statement and a processor MUST prefer them, so that two
processors reading one schema do not part company. transfer is
Vasters Expires 7 February 2027 [Page 104]
Internet-Draft JSON Structure Semantic Annotations August 2026
narrower still: where transfer is linear, it overrides the transfer
characteristics code point, and where transfer is asDefined or
absent, that code point governs.
11.1.3. The channels Property
channels MUST be a non-empty array of names of direct properties of
the annotated object or tuple, all distinct, mapped by position onto
the channels of the space in the order the identified definition
declares them. Except where packing is present, the number of
channels supplied MUST equal the number the identified space defines,
and an opacity channel is not one of them. As with coordinates and
components, the ordering is an assertion by the schema author and is
never inferred from property order, property names, or position in a
tuple.
Where packing is absent, either every name is that of a property of
numeric type, or the array holds exactly one name, that of a property
whose type is array or tuple and whose elements are of numeric type,
in which case the elements of that property supply the channels in
order. Where packing is present, the array holds exactly one name,
that of a property of type string, and the channels are read out of
that one value as Section 11.1.4 states.
This document does not fix the range or the unit of a channel value.
Where the identified definition does not establish them, as it does
not for a device control value, the schema SHOULD declare them, by a
unit annotation, by a numeric range, or in the description of the
property. The channels of one element SHOULD share one range
convention. A packing establishes both, and a schema carrying one
declares neither.
11.1.4. The packing Property
A color is often carried not as a set of numbers but as one string
that has all of them inside it. The hexadecimal notation is the
commonest such string in the world, and it asserts four things at
once that the numbers alone do not: that the order is red, green,
blue; that each channel is eight bits; that the range runs from zero
to two hundred and fifty-five; and, in the CSS reading, that the
space is sRGB with its transfer function applied. A reader who knows
the convention supplies all four. This keyword exists so that they
need not be known.
packing, when present, states that one string property carries every
channel of the element. Its value MUST be hexRgb or hexRgba.
Vasters Expires 7 February 2027 [Page 105]
Internet-Draft JSON Structure Semantic Annotations August 2026
+=========+====================================================+
| Value | Meaning |
+=========+====================================================+
| hexRgb | Three channels in three or six hexadecimal digits. |
+---------+----------------------------------------------------+
| hexRgba | Three channels and an opacity in four or eight |
| | hexadecimal digits. |
+---------+----------------------------------------------------+
Table 24
The value of the named property MUST consist of hexadecimal digits,
optionally preceded by a single #, and MUST hold three or six digits
under hexRgb and four or eight under hexRgba. The letters are case-
insensitive, as [CSS-COLOR-4] says in as many words: "the case of the
letters doesn't matter - #00ff00 is identical to #00FF00". The # is
part of the CSS token rather than of the notation, and a schema
requiring one form or forbidding the other states so by a pattern
[JSTRUCT-VALIDATION]; CSS itself accepts the bare form under the
quirks mode of [CSS-COLOR-4].
In the six-digit and eight-digit forms each successive pair of digits
is one channel, read as an integer from zero to two hundred and
fifty-five, where zero is the minimum of that channel and two hundred
and fifty-five is its maximum. In the three-digit and four-digit
forms each single digit stands for the pair obtained by writing it
twice, so that #123 is #112233. The order is fixed by this document
and is red, green, blue, and, under hexRgba, opacity. It is not
taken from the order the identified definition declares, and an
element whose identified space declares its channels in any other
order MUST NOT use a packing.
The identified space MUST define exactly three channels, and they
MUST be additive primaries. alpha MUST NOT be present where packing
is hexRgba, whose fourth channel is the opacity; alphaMode MAY be
present there and applies to it. alpha MAY be present where packing
is hexRgb, which carries none.
A packing carries eight bits for each channel, which is not enough
resolution for values proportional to light, so transfer SHOULD be
asDefined or absent where packing is present.
Vasters Expires 7 February 2027 [Page 106]
Internet-Draft JSON Structure Semantic Annotations August 2026
The space is still named by reference, and this document does not
assume one. A bare hexadecimal string in a document that says
nothing further is sRGB only because CSS says so, and CSS says so of
the CSS notation and not of the digits: hex colors are among those
that "resolve to sRGB" [CSS-COLOR-4]. A record carrying the same six
digits for a wide-gamut display means a different color, and the
difference is invisible in the value.
The following excerpt is a design token whose color is written the
way a stylesheet would write it.
{
"name": "BrandColorToken",
"type": "object",
"colorSpaces": [
{
"reference":
"https://www.w3.org/TR/css-color-4/#predefined-sRGB",
"kind": "iec",
"channels": ["value"],
"packing": "hexRgba"
}
],
"properties": {
"token": {
"type": "string"
},
"value": {
"type": "string",
"pattern": "^#[0-9a-fA-F]{8}$"
}
},
"required": ["token", "value"],
"additionalProperties": false
}
11.1.5. The alpha and alphaMode Properties
alpha, when present, MUST name a direct property of numeric type
carrying opacity, distinct from every name in channels. Its value is
a dimensionless fraction from zero to one unless the property
declares otherwise by a unit annotation or a numeric range, and where
it declares otherwise a processor MUST reduce it to that fraction
before applying alphaMode. alphaMode MUST NOT be present when both
alpha is absent and packing is not hexRgba, and states how the
channel values stand to the opacity, wherever that opacity is
carried. When present, its value MUST be straight or premultiplied.
Vasters Expires 7 February 2027 [Page 107]
Internet-Draft JSON Structure Semantic Annotations August 2026
+===============+======================================+
| Value | Meaning |
+===============+======================================+
| straight | The channel values are independent |
| | of the opacity value. |
+---------------+--------------------------------------+
| premultiplied | The channel values have already been |
| | multiplied by the opacity value. |
+---------------+--------------------------------------+
Table 25
Where an opacity is carried and alphaMode is absent, the value is
straight. That is also the reading a packed hexadecimal opacity
carries on its own, since the notation of [CSS-COLOR-4] does not
premultiply.
The two are not distinguishable by inspection, except at an opacity
of zero, where the premultiplied channels are all zero and the color
is gone. The PNG specification states its own choice in as many
words: "The color values in a pixel are not premultiplied by the
alpha value assigned to the pixel. This rule is sometimes called
'unassociated' or 'non-premultiplied' alpha", and, flatly, "PNG does
not use premultiplied alpha" [PNG3]. Formats that do premultiply
exist, and values carried from one to the other without the
conversion are wrong everywhere the opacity is neither zero nor one.
11.1.6. The transfer Property
transfer, when present, states whether the channel values carry the
transfer function of the identified space or are proportional to
light. Its value MUST be asDefined or linear.
+===========+=====================================================+
| Value | Meaning |
+===========+=====================================================+
| asDefined | The values carry the transfer function the |
| | identified definition establishes. |
+-----------+-----------------------------------------------------+
| linear | The values are proportional to radiometric |
| | quantity, taking the primaries and white point of |
| | the identified space but not its transfer function. |
+-----------+-----------------------------------------------------+
Table 26
When absent, the value is asDefined.
Vasters Expires 7 February 2027 [Page 108]
Internet-Draft JSON Structure Semantic Annotations August 2026
linear is what a renderer means when it calls a color energy-linear.
A space and its linear counterpart are commonly given the same name,
and the two are far apart: under the transfer function the ICC
registry publishes for sRGB, a channel value of 0.5 stands for
approximately 0.214 of the light that a channel value of 1.0 stands
for [ICC-REGISTRY]. Arithmetic on color is defined on the linear
values, and the PNG specification requires compositing to be
performed on "intensity samples (not gamma-encoded samples)" [PNG3].
11.1.7. The illuminant and observer Properties
illuminant and observer, when present, state the conditions the
values are relative to. illuminant names a standard illuminant, and
SHOULD use a designation of [CIE015]. observer names a standard
colorimetric observer; it is an open enumeration, and the values
defined here are cie-1931-2 for the 1931 standard colorimetric
observer and cie-1964-10 for the 1964 supplementary standard
colorimetric observer.
A space whose values are tristimulus quantities, or are computed from
them, does not by itself establish either. The definition of the
1976 L*a*b* space says as much: it "is applicable to tristimulus
values calculated using colour-matching functions of the CIE 1931
standard colorimetric system or the CIE 1964 standard colorimetric
system" [ISO11664-4]. Values computed under the two observers from
one sample differ, and nothing in the values records which was used.
Where the identified definition does not establish the illuminant and
the observer, a schema SHOULD declare illuminant and observer. Where
the definition does establish them and the declared members disagree
with it, the declared members prevail and a processor MUST prefer
them, for the reason that the schema author is stating the condition
these values were computed under and the definition is stating the
condition its class of values is customarily computed under. A
processor SHOULD report the disagreement, and MUST NOT treat it as
making the schema invalid.
Vasters Expires 7 February 2027 [Page 109]
Internet-Draft JSON Structure Semantic Annotations August 2026
Published measurement data shows both practices. The
characterization datasets of the International Color Consortium carry
their conditions in the file itself. One widely used print dataset
opens by stating its instrument geometry as "D50, 2 degree, geometry
45/0, no polarisation filter, white backing, according to ISO
13655:2009 M1", then repeats the illuminant and the observer angle in
fields of their own and records the national laboratory its
measurements are traceable to [ICC-REGISTRY]. Reference data for a
widely used color target, published by the maker of that target,
states the measurement condition and the filter and names neither an
illuminant nor an observer anywhere in the file. The second is not
usable as reference data without information from outside it, and a
schema is a place to put that information.
An identifier of a color space is also an identifier of an edition of
it. The reference values for that same color target were revised,
and for the white patch alone the lightness moved by more than one
unit and the yellow-blue coordinate by nearly two, under an unchanged
product name. A schema naming the space but not the edition
describes two different sets of numbers.
11.1.8. Example
A characterization dataset pairs the device values that were sent to
a press with the color that was measured off the printed result. The
two are in different spaces, which is why the keyword is an array,
and only one of them is a color space in the colorimetric sense at
all; the other is a set of device control values whose meaning is
precisely the measurement it is paired with.
Vasters Expires 7 February 2027 [Page 110]
Internet-Draft JSON Structure Semantic Annotations August 2026
========== NOTE: '\' line wrapping per RFC 8792 ===========
{
"name": "CharacterizationPatch",
"type": "object",
"colorSpaces": [
{
"reference":
"https://registry.color.org/cmyk-registry/fogra51",
"kind": "icc-registry",
"channels": ["c", "m", "y", "k"]
},
{
"reference": "https://cie.co.at/publications/\
colorimetry-part-4-cie-1976-lab-colour-space-1",
"kind": "cie",
"channels": ["lStar", "aStar", "bStar"],
"illuminant": "D50",
"observer": "cie-1931-2"
}
],
"properties": {
"sampleId": { "type": "int32" },
"c": { "type": "double", "unit": "%" },
"m": { "type": "double", "unit": "%" },
"y": { "type": "double", "unit": "%" },
"k": { "type": "double", "unit": "%" },
"lStar": { "type": "double" },
"aStar": { "type": "double" },
"bStar": { "type": "double" }
},
"required": [
"sampleId", "c", "m", "y", "k", "lStar", "aStar", "bStar"
],
"additionalProperties": false
}
The instance below is one patch of that dataset, the solid of the
third ink.
Vasters Expires 7 February 2027 [Page 111]
Internet-Draft JSON Structure Semantic Annotations August 2026
{
"sampleId": 649,
"c": 0.0,
"m": 0.0,
"y": 100.0,
"k": 0.0,
"lStar": 88.94,
"aStar": -4.04,
"bStar": 92.37
}
The three measured values are a position in a space that is undefined
until the illuminant and the observer are known, and the file the
numbers came from is one of the ones that says so. The annotation
carries what that file carries, in a place a processor can read.
12. Signal Channel Annotations
The keywords of this section resolve components onto the channels of
a named space, as Section 11 does for color. A signal is a bundle of
channel numbers that means nothing until something states which
channel is which, what the numbers stand relative to, and how they
are encoded. Color carries that in colorSpaces; audio and multiband
imaging carry it here.
12.1. The audioChannels Keyword
The audioChannels keyword identifies the channel layout in which
audio sample values held in properties of an object or tuple are to
be interpreted, the level the samples are relative to, and the
encoding they carry.
An audio sample is a measurement of a signal, and a set of samples is
not sound until something states which loudspeaker or which role each
channel drives, what the numbers stand relative to, and whether they
are amplitudes or a companded encoding of them. A bare array carries
none of that, and the conventions that carry it differ between
formats.
When present, audioChannels MUST be a non-empty array. Each element
MUST be an object with a REQUIRED reference, a REQUIRED kind, a
REQUIRED channels, an OPTIONAL levelReference, and an OPTIONAL
encoding, and no other members. The keyword is an array because one
record may carry more than one channel group, as a programme does
when a commentary track accompanies a music-and-effects mix.
Vasters Expires 7 February 2027 [Page 112]
Internet-Draft JSON Structure Semantic Annotations August 2026
12.1.1. The reference and kind Properties
reference MUST identify one channel layout whose definition
establishes an ordered set of channels, each with a loudspeaker
position or a role. Where kind is type it MUST be a type reference {
"$ref": <JSON Pointer> } [JSTRUCT-CORE] to a shareable type
definition, and otherwise it MUST be an absolute URI [RFC3986]. kind
classifies which definition model the reference identifies. It is an
open enumeration; the following values are defined here:
+======+=============================================+
| Kind | Referenced definition |
+======+=============================================+
| itu | A Recommendation of the International |
| | Telecommunication Union, such as the |
| | loudspeaker configurations of [ITU-BS2051]. |
+------+---------------------------------------------+
| type | A meta-type in the annotated schema, as |
| | Section 8 describes. |
+------+---------------------------------------------+
Table 27
A layout recommendation such as [ITU-BS2051] defines several
configurations, and a bare reference to it names the recommendation
rather than one of them; a schema that must pin one configuration
deep-links to it or carries it as a type. Where the recommendation
mints no per-configuration URI, the deep link is a fragment that
names the configuration in the recommendation's own notation, as
#0+5+0 names its five-loudspeaker system with a low-frequency-effects
channel; the fragment identifies the configuration whether or not the
recommendation serves it. A processor is not required to dereference
the URI. This document does not define a resolution protocol, URI
layout, storage model, or definition serialization.
12.1.2. The channels Property
channels MUST be a non-empty array of names of direct properties of
the annotated object or tuple, all distinct, mapped by position onto
the channels of the layout in the order the identified definition
declares them. The number of channels supplied MUST equal the number
the identified layout defines. As with coordinates and the channels
of colorSpaces, the ordering is an assertion by the schema author and
is never inferred from property order, property names, or position in
a tuple. A low-frequency-effects channel is one of the channels, in
the position the layout assigns it, and is not inferred from a
property name. Either every name is that of a property of numeric
type, or the array holds exactly one name, that of a property whose
Vasters Expires 7 February 2027 [Page 113]
Internet-Draft JSON Structure Semantic Annotations August 2026
type is array or tuple and whose elements are of numeric type, in
which case the elements of that property supply the channels in
order.
12.1.3. The levelReference Property
levelReference, when present, states what the sample amplitudes are
relative to. Its values, their meanings, and its openness are those
of the levelReference of measurementConditioning (Section 7.1.3),
which defines them. Under fullScale the numeric range of the samples
is stated by the property carrying them and not by this value.
The default differs from that of measurementConditioning. Here,
absence means fullScale, because digital audio samples are referred
to full scale unless something says otherwise. Under
measurementConditioning, absence means that no level reference is
stated, because a conditioned measurement has no comparable default.
Programme loudness is not a per-sample reference: it is an
integrated, gated, frequency-weighted measure of a whole programme,
defined by [ITU-BS1770] and given a target by [EBU-R128], and a
schema that carries it carries it as its own annotated value, not as
the level reference of the channels.
12.1.4. The encoding Property
encoding, when present, states how the stored numbers stand to
amplitude. Its value MUST be one of the values below or an absolute
URI identifying another encoding.
Vasters Expires 7 February 2027 [Page 114]
Internet-Draft JSON Structure Semantic Annotations August 2026
+========+=================================================+
| Value | Meaning |
+========+=================================================+
| linear | The numbers are proportional to amplitude, and |
| | full scale is the range the annotated member's |
| | declared type permits. |
+--------+-------------------------------------------------+
| float | The numbers are proportional to amplitude and |
| | full scale is unit magnitude, so a sample of |
| | 1.0 is at full scale. A magnitude greater than |
| | one is legal and is a level above full scale. |
+--------+-------------------------------------------------+
| aLaw | Each channel value is the eight-bit A-law code |
| | word that [ITU-G711] defines. |
+--------+-------------------------------------------------+
| muLaw | Each channel value is the eight-bit mu-law code |
| | word that [ITU-G711] defines. |
+--------+-------------------------------------------------+
Table 28
Where absent, the encoding is linear.
The division between linear and float is the scale, not the storage
type. A member of floating-point type whose samples run to the range
of an integer quantization is linear; a member whose samples are
normalized to unit magnitude is float, whatever its declared type.
The distinction matters because every value validates under either
and only one of them makes a decibel level or a sum of channels come
out right, and because a float member may legitimately carry a
magnitude greater than one that a reader must not treat as an error.
Under aLaw or muLaw each channel value is an integer from zero to two
hundred and fifty-five, and a reader restores amplitude by the
inverse companding before any arithmetic.
The enumeration is open because a sample encoding is a definition
maintained elsewhere, as G.711 companding is. A value that is a URI
SHOULD identify a definition of the encoding. A processor that does
not know a value MUST preserve it, MUST NOT reject the schema for
carrying it, and MUST NOT assume that the numbers are proportional to
amplitude; the check is indeterminate rather than incorrect. A
compressed bitstream is not a set of channel members and is outside
this keyword whatever its encoding is called.
Object-based and scene-based audio, in which a sample is not one
loudspeaker, are not channel layouts in this sense; they are
described by the Audio Definition Model [ITU-BS2076] and are outside
Vasters Expires 7 February 2027 [Page 115]
Internet-Draft JSON Structure Semantic Annotations August 2026
this keyword. The time axis of audio, the sample rate, is a regular
temporal cadence and is carried by temporalReferenceSystem and
cadence (Section 9.4), not here.
12.1.5. Example
The record below is one multichannel sample frame of a five-channel-
with-LFE programme, whose layout is the 0+5+0 system of [ITU-BS2051].
The six property names are the schema author's; the order of channels
is what binds them to the layout.
{
"name": "SurroundSampleFrame",
"type": "object",
"audioChannels": [
{
"reference": "https://www.itu.int/rec/R-REC-BS.2051/en#0+5+0",
"kind": "itu",
"channels": ["l", "r", "c", "lfe", "ls", "rs"],
"levelReference": "fullScale",
"encoding": "linear"
}
],
"properties": {
"frameIndex": { "type": "int64" },
"l": { "type": "double" },
"r": { "type": "double" },
"c": { "type": "double" },
"lfe": { "type": "double" },
"ls": { "type": "double" },
"rs": { "type": "double" }
},
"required": ["frameIndex", "l", "r", "c", "lfe", "ls", "rs"],
"additionalProperties": false
}
12.2. The spectralBands Keyword
The spectralBands keyword identifies the spectral bands onto which
the components of a multiband value held in properties of an object
or tuple are resolved, in the order a named sensor or band set
declares them.
Vasters Expires 7 February 2027 [Page 116]
Internet-Draft JSON Structure Semantic Annotations August 2026
A multiband pixel is a row of numbers, one per band, and it means
nothing until something states which wavelengths each band covers and
what physical quantity the number is. The bands of one sensor are
not the bands of another even where they are given the same colour
name, and a raw count is not a radiance until the sensor's
calibration is applied.
When present, spectralBands MUST be a non-empty array. Each element
MUST be an object with a REQUIRED reference, a REQUIRED kind, a
REQUIRED bands, and an OPTIONAL calibration, and no other members.
The keyword is an array because one record may resolve its components
onto more than one band set, as a fused product does when it carries
bands from two instruments.
12.2.1. The reference and kind Properties
reference MUST identify one band set whose definition establishes an
ordered set of bands, each with a wavelength range. Where kind is
type it MUST be a type reference { "$ref": <JSON Pointer> }
[JSTRUCT-CORE] to a shareable type definition, and otherwise it MUST
be an absolute URI [RFC3986]. kind classifies which definition model
the reference identifies. It is an open enumeration; the following
values are defined here:
+========+=========================================+
| Kind | Referenced definition |
+========+=========================================+
| sensor | A band set published by the operator of |
| | an instrument, such as the Operational |
| | Land Imager bands of [USGS-LANDSAT]. |
+--------+-----------------------------------------+
| type | A meta-type in the annotated schema, as |
| | Section 8 describes. |
+--------+-----------------------------------------+
Table 29
A publication that lists the band sets of several instruments names
one of them by a deep link, a fragment naming the instrument where
the publisher mints no per-instrument URI, as #landsat-8-9-oli names
the Operational Land Imager; the fragment identifies the band set
whether or not the publication serves it. A processor is not
required to dereference the URI. This document does not define a
resolution protocol, URI layout, storage model, or definition
serialization.
Vasters Expires 7 February 2027 [Page 117]
Internet-Draft JSON Structure Semantic Annotations August 2026
12.2.2. The bands Property
bands MUST be a non-empty array of names of direct properties of the
annotated object or tuple, all distinct, mapped by position onto the
bands of the set in the order the identified definition declares
them. The number of bands supplied MUST equal the number the
identified set defines. As with the channels of colorSpaces, the
ordering is an assertion by the schema author and is never inferred
from property order, property names, or position in a tuple. Either
every name is that of a property of numeric type, or the array holds
exactly one name, that of a property whose type is array or tuple and
whose elements are of numeric type, in which case the elements of
that property supply the bands in order.
12.2.3. The calibration Property
calibration, when present, states what physical quantity each band
value is. It is an open enumeration; the values defined here are:
+===============+==============================================+
| Value | Meaning |
+===============+==============================================+
| digitalNumber | The values are quantized, calibrated, scaled |
| | digital numbers in the identified product |
| | encoding, which become a physical quantity |
| | only when the per-band coefficients of the |
| | acquisition are applied. |
+---------------+----------------------------------------------+
| radiance | The values are spectral radiance, and their |
| | unit is stated by JSON Structure Units |
| | [JSTRUCT-UNITS]. |
+---------------+----------------------------------------------+
| reflectance | The values are reflectance, a dimensionless |
| | fraction, of the kind the identified product |
| | defines, such as top-of-atmosphere planetary |
| | reflectance with or without a solar-angle |
| | correction; where they are stored scaled, |
| | the property states the scale. |
+---------------+----------------------------------------------+
Table 30
Where absent, the calibration is not established by this annotation
and the identified definition or the unit of the property governs.
The rescaling from a digital number to radiance or reflectance is
per-band; for the Landsat imagers it is a multiplicative and an
additive coefficient for each band, delivered in the product metadata
[USGS-LANDSAT-L1], and a schema that holds digital numbers holds
Vasters Expires 7 February 2027 [Page 118]
Internet-Draft JSON Structure Semantic Annotations August 2026
those coefficients as their own values. A quantity the values
defined here do not name, such as brightness temperature, is carried
as an open value.
12.2.4. Example
The record below is one pixel of a nine-band Operational Land Imager
scene, whose bands are those of [USGS-LANDSAT], carried as
reflectance.
========== NOTE: '\' line wrapping per RFC 8792 ===========
{
"name": "OliPixel",
"type": "object",
"spectralBands": [
{
"reference": "https://www.usgs.gov/faqs/\
what-are-band-designations-landsat-satellites",
"kind": "sensor",
"bands": [
"coastalAerosol", "blue", "green", "red",
"nir", "swir1", "swir2", "pan", "cirrus"
],
"calibration": "reflectance"
}
],
"properties": {
"column": { "type": "int32" },
"row": { "type": "int32" },
"coastalAerosol": { "type": "double" },
"blue": { "type": "double" },
"green": { "type": "double" },
"red": { "type": "double" },
"nir": { "type": "double" },
"swir1": { "type": "double" },
"swir2": { "type": "double" },
"pan": { "type": "double" },
"cirrus": { "type": "double" }
},
"required": [
"column", "row", "coastalAerosol", "blue", "green", "red",
"nir", "swir1", "swir2", "pan", "cirrus"
],
"additionalProperties": false
}
Vasters Expires 7 February 2027 [Page 119]
Internet-Draft JSON Structure Semantic Annotations August 2026
13. Conformance
13.1. Check Outcomes
A check defined by this document has one of three outcomes. It is
valid when a processor evaluated it and it held, invalid when a
processor evaluated it and it did not hold, and indeterminate when a
processor did not evaluate it because a definition it depends on was
not resolved.
A processor MUST report the three outcomes distinctly. It MUST NOT
report an indeterminate check as valid, MUST NOT reject a schema
solely because a check was indeterminate, and MUST NOT act on an
annotation as though an indeterminate check had held.
A rule whose subject lies within the schema is always evaluable, and
a check of such a rule is never indeterminate. A rule whose subject
is an external definition is indeterminate for as long as that
definition is unresolved.
Which definitions a processor holds is a deployment matter, so two
conforming processors MAY reach different outcomes for one schema.
They MUST differ only in that one returns indeterminate where the
other returns valid or invalid. A processor MUST NOT return valid
where a processor holding the definition would return invalid.
A profile, a deployment, or an agreement between parties MAY require
that named checks be evaluated rather than left indeterminate. This
document requires it of no check.
13.2. Schema Conformance
A conforming schema selects the versioned extension meta-schema URI.
It MAY use any subset of the annotations defined by this document,
including none, and it MUST NOT be rejected merely because an
annotation or annotated property is absent.
Every annotation that is present:
* MUST occur at an attachment point permitted by this document;
* MUST have the defined value shape and use an allowed kind,
semanticRole, or referenceRole value;
* MUST NOT repeat, within one containing type, a semanticRole that
Section 5.3 states identifies one position;
* MUST be compatible with the Core type of the annotated schema; and
Vasters Expires 7 February 2027 [Page 120]
Internet-Draft JSON Structure Semantic Annotations August 2026
* MUST satisfy the applicable rules of JSON Structure Units
[JSTRUCT-UNITS].
Validation MUST reject malformed annotations and invalid identifiers
or values within annotations, and those checks are never
indeterminate. External resolution, domain-of-validity, mapping-
review, and transformation checks are indeterminate while the
definition they depend on is unresolved, and Section 13.1 states how
a processor reports them.
13.3. Processing Conformance
A conforming processor MUST preserve declarations, externally
resolved facts, and inferences separately. It MUST preserve the
differences among an observation act, its result, an observable-
property identity, a definition URI, an identifiable temporal object,
and a temporal-position value.
A processor MUST NOT infer:
* any semanticRole, observed-property annotation, concept binding,
derivation, statistic, or cadence from a name, label, description,
type, unit, position, or sample;
* a referenceRole, or the member of a meta-type that a mapping
property names, from a member name;
* graph structure, node identity, statements, or entailment from a
concept binding, or a term of one vocabulary from a term of
another;
* identity or semantic equivalence from labels, closeMatch,
hierarchy, relatedness, or QuantityKind classification;
* a feature, procedure, or identity absent from the corresponding
semanticRole, or a proximate feature from an ultimate feature or
conversely;
* a temporal reference regime from a non-Core or ambiguous encoding;
* metric intervals from ordinal positions or an untilNext end from
cadence;
* complete coverage from interval or accumulation;
* that absent quality means acceptable quality;
Vasters Expires 7 February 2027 [Page 121]
Internet-Draft JSON Structure Semantic Annotations August 2026
* a coordinate, vector-frame, or linear reference binding from names
or samples;
* the direction, sense, or component order of a frame
transformation, or the variance of a vector or tensor quantity,
from member names, from the values themselves, or from the frames
the transformation runs between;
* a color space, an illuminant, an observer, a transfer function, or
an alpha mode from channel names, from the range the channel
values fall in, or from the number of channels present;
* an audio channel layout, level reference, or encoding; a spectral
band set or calibration; a code-list binding; or a measurement
weighting, time weighting, or level reference, from names,
samples, units, or the number of members present;
* that members sharing a name prefix, a unit, or an observed
property are the components of one vector quantity;
* an observation entity, or any class, identity, or relationship of
an observation model, from the roles a schema declares;
* an instruction to perform, repeat, or recompute an operation from
a keyword that names one; or
* permission to aggregate, convert, transform, reject outliers, or
infer causality.
A processor that selects one temporal position as the event-time axis
of a record, for windowing, ordering, or watermarking, SHOULD select
the member annotated phenomenonTime, or, where the record bounds the
period at both ends, the member annotated phenomenonTimeStart. It
SHOULD NOT select a member annotated resultTime, ingestionTime,
scheduledTime, or actualTime for that purpose. Those roles state the
handling of the record and not the time of the phenomenon, and a
window built on them reports the behaviour of the pipeline rather
than of the world.
Where a processor needs both axes and its execution model admits only
one, the phenomenon-time member is the recommended axis, and the
operational position is carried as an ordinary value. A processor
that departs from this SHOULD record the position it selected, so
that a reader of the output is not left to infer which axis produced
it.
Vasters Expires 7 February 2027 [Page 122]
Internet-Draft JSON Structure Semantic Annotations August 2026
A record annotating no phenomenon-time role supplies no phenomenon-
time axis. A processor MUST NOT construct one from a member name,
and MUST NOT read an operational position as one. It MAY still
window on an operational position, which states when the record was
handled.
A processor MAY ignore this extension. A processor claiming support
MUST treat unresolved identifiers, domains, mappings, or conversions
as indeterminate rather than compatible.
13.4. Inheritance and Imports
An annotation on an inherited property or type remains part of the
effective schema. Core inheritance does not define a local override
of an inherited property. Cross-property rules MUST be checked
against the effective inherited type.
JSON Structure Import copies complete definitions, including
annotations [JSTRUCT-IMPORT]. Shadowing replaces the complete
imported definition; it does not merge individual annotations.
Member names stated by an annotation are resolved as Section 3
requires: against the effective definition of the annotated type, and
against declared property names rather than serialized ones.
An annotation belongs to the definition it is written on, so
annotations are part of what a type means rather than of how one
schema uses it. A schema that needs different annotations for the
same structure shadows the definition and restates them, or defines a
distinct type. This document defines no overlay by which a schema
attaches annotations to a definition it does not own.
Where a type would inherit the same keyword from more than one base,
the derived definition MUST state that keyword itself, and the stated
value is the effective one. A definition that leaves two inherited
values of one keyword in force is not conforming, and a processor
MUST NOT select between them.
14. Extension Meta-Schema
The extension meta-schema is published at:
https://json-structure.org/meta/semantic-annotations/v0/#
It offers one feature, JSONStructureSemanticAnnotations, whose add-
ins contribute the keywords defined here to the Core property,
object, tuple, array, set, map, and choice definitions. A schema
activates this specification by selecting that URI and naming the
Vasters Expires 7 February 2027 [Page 123]
Internet-Draft JSON Structure Semantic Annotations August 2026
feature in $uses. The meta-schema enables JSON Structure Units,
Import, Conditional Composition, and Validation. The annotations
carry no profile or version member; the versioned meta-schema URI is
the version identifier.
The meta-schema validates the shape of each annotation defined here:
the presence and form of its members, the enumerations that Section 3
states are closed, and the form required of a reference for the
accompanying kind. It does not express a rule whose subject lies
outside the annotated node. Such rules, including every rule about a
property that an annotation names and every rule about a definition
that a reference identifies, are checked against the effective schema
rather than by the meta-schema alone. No companion reference type or
import is required.
15. Security Considerations
Incorrect or malicious catalog entries, labels, mappings, feature
identities, or procedure identities can cause results from different
subjects, acts, or concepts to be combined. Implementations MUST
preserve catalog-URI identity, MUST NOT infer equivalence from
discovery labels, and MUST NOT treat an unreviewed or non-exact
mapping as approval. Catalog write access and mapping review
therefore require authentication, authorization, audit, and
provenance. Deprecation alternatives are migration advice, not
automatic substitutions.
No annotation is checked against the data it describes. Validation
confirms that a named member exists, that a closed enumeration holds,
and that components and units agree in number and kind; it cannot
confirm that a reference still identifies the definition the values
are actually expressed against. An annotation is therefore a claim
that can be true when written and false later without anything
failing: an instrument is recalibrated, a station is resurveyed onto
a new datum, a producer reorders channels or changes a rate, a code
list is superseded. The schema continues to validate and the
annotation continues to read as authoritative.
Stale annotation is for that reason more dangerous than absent
annotation. The prohibitions in Section 13.3 guard the absent case,
where a processor is required to decline rather than guess; they do
not guard the stale case, where a processor holds an explicit
statement, has no ground to doubt it, and proceeds with a combination
it would otherwise have refused. A schema author MUST revise the
annotations of a schema in the same change that alters what the
schema describes, and a consumer MUST NOT treat an annotation as
evidence more current than the schema revision carrying it.
Vasters Expires 7 February 2027 [Page 124]
Internet-Draft JSON Structure Semantic Annotations August 2026
The same property makes annotations a target. Modifying a schema
changes what data means without touching the data, without failing
validation, and without any signal to a consumer: a substituted CRS
reference relocates every coordinate, an alphaMode moved between
straight and premultiplied alters every composite, an altered
levelReference shifts every level by an amount large enough to matter
and plausible enough to pass review. Schema distribution therefore
needs the integrity protection the data needs, and a change to an
annotation warrants the review a change to a type warrants.
Incorrect temporal roles, boundaries, reference systems,
transformations, or domains of validity can reorder positions or
create false coverage. Cadence MUST NOT synthesize a missing
untilNext successor. Incorrect CRS, axis order, LRS, measure origin,
unit, or direction can place a feature incorrectly. Processors MUST
NOT perform temporal, coordinate, linear, or unit transformations
without validating authoritative definitions.
Remote registries, schemas, vocabularies, procedures, mapping
targets, and reference systems are untrusted input. Implementations
SHOULD use HTTPS where available, bounded retrieval, caching with
version awareness, allow-lists where appropriate, cycle detection,
and explicit trust decisions.
15.1. Privacy Considerations
Catalog labels and mappings, procedure and feature identities,
locations, times, statuses, and quality can reveal sensitive
operations or subjects. Hidden labels are not an access-control
mechanism. This specification grants no access and does not replace
minimization, privacy review, retention, or export controls.
Dereferencing a reference can disclose processor interest to the
party that serves the definition.
16. IANA Considerations
This document has no IANA actions.
17. References
17.1. Normative References
[ISO19108] International Organization for Standardization, "ISO
19108:2002 Geographic information - Temporal schema",
2002, <https://www.iso.org/standard/26013.html>.
Vasters Expires 7 February 2027 [Page 125]
Internet-Draft JSON Structure Semantic Annotations August 2026
[ISO19111] International Organization for Standardization, "ISO
19111:2019 Geographic information - Referencing by
coordinates", 2019,
<https://www.iso.org/standard/74039.html>.
[ISO19148] International Organization for Standardization, "ISO
19148:2021 Geographic information - Linear referencing",
2021, <https://www.iso.org/standard/75147.html>.
[JSTRUCT-CORE]
Vasters, C., "JSON Structure: Core", Work in Progress,
Internet-Draft, draft-vasters-json-structure-core-04, 8
June 2026, <https://datatracker.ietf.org/doc/html/draft-
vasters-json-structure-core-04>.
[JSTRUCT-UNITS]
Vasters, C., "JSON Structure: Symbols, Scientific Units,
and Currencies", Work in Progress, Internet-Draft, draft-
vasters-json-structure-units-03, 8 June 2026,
<https://datatracker.ietf.org/doc/html/draft-vasters-json-
structure-units-03>.
[JSTRUCT-VALIDATION]
Vasters, C., "JSON Structure: Validation Extensions", Work
in Progress, Internet-Draft, draft-vasters-json-structure-
validation-03, 8 June 2026,
<https://datatracker.ietf.org/doc/html/draft-vasters-json-
structure-validation-03>.
[OGC-NAMES]
Open Geospatial Consortium, "OGC Name Type Specification -
definitions - part 1 - basic name", n.d.,
<https://docs.ogc.org/pol/09-048r6.html>.
[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
Requirement Levels", BCP 14, RFC 2119,
DOI 10.17487/RFC2119, March 1997,
<https://www.rfc-editor.org/rfc/rfc2119>.
[RFC3339] Klyne, G. and C. Newman, "Date and Time on the Internet:
Timestamps", RFC 3339, DOI 10.17487/RFC3339, July 2002,
<https://www.rfc-editor.org/rfc/rfc3339>.
[RFC3986] Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform
Resource Identifier (URI): Generic Syntax", STD 66,
RFC 3986, DOI 10.17487/RFC3986, January 2005,
<https://www.rfc-editor.org/rfc/rfc3986>.
Vasters Expires 7 February 2027 [Page 126]
Internet-Draft JSON Structure Semantic Annotations August 2026
[RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC
2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174,
May 2017, <https://www.rfc-editor.org/rfc/rfc8174>.
17.2. Informative References
[CCSDS-ADM]
Consultative Committee for Space Data Systems, "Attitude
Data Messages, Recommended Standard, CCSDS 504.0-B-2, Blue
Book", January 2024,
<https://public.ccsds.org/Pubs/504x0b2.pdf>.
[CCSDS-ADM1]
Consultative Committee for Space Data Systems, "Attitude
Data Messages, Recommended Standard, CCSDS 504.0-B-1, Blue
Book, including Technical Corrigendum 1 (July 2015)", May
2008, <https://public.ccsds.org/Pubs/504x0b1c1s.pdf>.
[CF-STANDARD-NAMES]
CF Conventions, "CF Standard Name Table", n.d.,
<https://cfconventions.org/Data/cf-standard-
names/current/build/cf-standard-name-table.html>.
[CIE015] International Commission on Illumination, "CIE 015:2018
Colorimetry, 4th Edition", 2018,
<https://cie.co.at/publications/colorimetry-4th-edition>.
[CSS-COLOR-4]
World Wide Web Consortium, "CSS Color Module Level 4",
n.d., <https://www.w3.org/TR/css-color-4/>.
[DCTERMS] Dublin Core Metadata Initiative, "DCMI Metadata Terms",
n.d., <https://www.dublincore.org/specifications/dublin-
core/dcmi-terms/>.
[EBU-R128] European Broadcasting Union, "EBU R 128: Loudness
normalisation and permitted maximum level of audio
signals", November 2023,
<https://tech.ebu.ch/publications/r128>.
[EPSG] International Association of Oil and Gas Producers, "EPSG
Geodetic Parameter Dataset", n.d., <https://epsg.org/>.
[FHWA-ARNOLD]
Federal Highway Administration, "All Road Network of
Linear Referenced Data", n.d.,
<https://www.fhwa.dot.gov/policyinformation/hpms/
arnold.cfm>.
Vasters Expires 7 February 2027 [Page 127]
Internet-Draft JSON Structure Semantic Annotations August 2026
[FHWA-HPMS]
Federal Highway Administration, "Highway Performance
Monitoring System Field Manual", n.d.,
<https://www.fhwa.dot.gov/policyinformation/hpms/
fieldmanual/>.
[GCMT-NDK] Global CMT Project, "Explanation of the ndk file format
used for the Global Centroid-Moment-Tensor catalog", 2006,
<https://www.ldeo.columbia.edu/~gcmt/projects/CMT/catalog/
allorder.ndk_explained>.
[IANA-LANGTAGS]
Internet Assigned Numbers Authority, "Language Subtag
Registry", n.d., <https://www.iana.org/assignments/
language-subtag-registry>.
[IANA-PROTOCOLS]
Internet Assigned Numbers Authority, "Protocol
Registries", n.d., <https://www.iana.org/protocols>.
[IATA-CODES]
International Air Transport Association, "Airline and
Airport Code Search", n.d.,
<https://www.iata.org/en/publications/directories/code-
search/>.
[ICAO7910] International Civil Aviation Organization, "Location
Indicators (Doc 7910)", n.d.,
<https://store.icao.int/en/location-indicators-doc-7910>.
[ICAO8643] International Civil Aviation Organization, "Aircraft Type
Designators (Doc 8643)", n.d., <https://www.icao.int/
operational-safety/doc-8643-aircraft-type-designators>.
[ICC-REGISTRY]
International Color Consortium, "ICC Characterization Data
Registry", n.d., <https://registry.color.org/>.
[ICC-SPEC] International Color Consortium, "Image technology colour
management - Architecture, profile format, and data
structure (ISO 15076-1:2025, ICC.1:2022, profile version
4.4)", 2022, <https://www.color.org/v4spec.xalter>.
[IEC61672-1]
International Electrotechnical Commission, "IEC
61672-1:2013 Electroacoustics - Sound level meters - Part
1: Specifications", 2013,
<https://webstore.iec.ch/en/publication/5708>.
Vasters Expires 7 February 2027 [Page 128]
Internet-Draft JSON Structure Semantic Annotations August 2026
[ISO639] International Organization for Standardization, "ISO 639:
Code for individual languages and language groups", n.d.,
<https://www.iso.org/iso-639-language-codes.html>.
[ISO1683] International Organization for Standardization, "ISO
1683:2015 Acoustics - Preferred reference values for
acoustical and vibratory levels", 2015,
<https://www.iso.org/standard/64648.html>.
[ISO3166] International Organization for Standardization, "ISO 3166:
Codes for the representation of names of countries and
their subdivisions", n.d.,
<https://www.iso.org/iso-3166-country-codes.html>.
[ISO4217] International Organization for Standardization, "ISO 4217:
Codes for the representation of currencies", n.d.,
<https://www.iso.org/iso-4217-currency-codes.html>.
[ISO11664-4]
International Commission on Illumination, "Colorimetry -
Part 4: CIE 1976 L*a*b* colour space (ISO/CIE
11664-4:2019)", 2019, <https://cie.co.at/publications/
colorimetry-part-4-cie-1976-lab-colour-space-1>.
[ISO19156] International Organization for Standardization, "ISO
19156:2023 Geographic information - Observations,
measurements and samples", 2023,
<https://www.iso.org/standard/82463.html>.
[ITU-BS1770]
International Telecommunication Union, "Recommendation
ITU-R BS.1770-5: Algorithms to measure audio programme
loudness and true-peak audio level", November 2023,
<https://www.itu.int/rec/R-REC-BS.1770/en>.
[ITU-BS2051]
International Telecommunication Union, "Recommendation
ITU-R BS.2051-3: Advanced sound system for programme
production", May 2022,
<https://www.itu.int/rec/R-REC-BS.2051/en>.
[ITU-BS2076]
International Telecommunication Union, "Recommendation
ITU-R BS.2076: Audio Definition Model", n.d.,
<https://www.itu.int/rec/R-REC-BS.2076/en>.
Vasters Expires 7 February 2027 [Page 129]
Internet-Draft JSON Structure Semantic Annotations August 2026
[ITU-G711] International Telecommunication Union, "Recommendation
ITU-T G.711: Pulse code modulation (PCM) of voice
frequencies", November 1988,
<https://www.itu.int/rec/T-REC-G.711>.
[ITU-H273] International Telecommunication Union, "Recommendation
ITU-T H.273: Coding-independent code points for video
signal type identification", July 2024,
<https://www.itu.int/rec/T-REC-H.273>.
[JSTRUCT-ALTNAMES]
Vasters, C., "JSON Structure: Alternate Names and
Descriptions", Work in Progress, Internet-Draft, draft-
vasters-json-structure-alternate-names-03, 8 June 2026,
<https://datatracker.ietf.org/doc/html/draft-vasters-json-
structure-alternate-names-03>.
[JSTRUCT-IMPORT]
Vasters, C., "JSON Structure: Import", Work in Progress,
Internet-Draft, draft-vasters-json-structure-import-03, 8
June 2026, <https://datatracker.ietf.org/doc/html/draft-
vasters-json-structure-import-03>.
[JSTRUCT-RELATIONS]
Vasters, C., "JSON Structure: Relations", Work in
Progress, Internet-Draft, draft-vasters-json-structure-
relations-00, 8 June 2026,
<https://datatracker.ietf.org/doc/html/draft-vasters-json-
structure-relations-00>.
[KITTI] Geiger, A., Lenz, P., Stiller, C., and R. Urtasun, "Vision
meets Robotics: The KITTI Dataset", 2013,
<https://www.cvlibs.net/publications/Geiger2013IJRR.pdf>.
[LOINC] Regenstrief Institute, "LOINC", n.d.,
<https://loinc.org/>.
[NAIF-QUAT]
NASA Jet Propulsion Laboratory, Navigation and Ancillary
Information Facility, "Quaternions White Paper", 30
November 2003, <https://naif.jpl.nasa.gov/pub/naif/misc/
Quaternion_White_Paper/Quaternions_White_Paper.pdf>.
[OGC-TOPIC2]
Open Geospatial Consortium, "OGC Abstract Specification
Topic 2: Referencing by coordinates", 2019,
<https://docs.ogc.org/as/18-005r4/18-005r4.html>.
Vasters Expires 7 February 2027 [Page 130]
Internet-Draft JSON Structure Semantic Annotations August 2026
[OGC-TOPIC25]
Open Geospatial Consortium, "OGC Abstract Specification
Topic 25: Abstract Conceptual Model for Time", n.d.,
<https://docs.ogc.org/as/23-049/23-049.html>.
[OWL2] World Wide Web Consortium, "OWL 2 Web Ontology Language
Document Overview", n.d.,
<https://www.w3.org/TR/owl2-overview/>.
[PNG3] World Wide Web Consortium, "Portable Network Graphics
(PNG) Specification (Third Edition)", 24 June 2025,
<https://www.w3.org/TR/png-3/>.
[PROV-O] World Wide Web Consortium, "PROV-O: The PROV Ontology",
n.d., <https://www.w3.org/TR/prov-o/>.
[QUDT] QUDT.org, "QUDT Ontologies", n.d.,
<https://www.qudt.org/>.
[RDF-CONCEPTS]
World Wide Web Consortium, "RDF 1.1 Concepts and Abstract
Syntax", n.d., <https://www.w3.org/TR/rdf11-concepts/>.
[RDF-SCHEMA]
World Wide Web Consortium, "RDF Schema 1.1", n.d.,
<https://www.w3.org/TR/rdf-schema/>.
[REP-103] Foote, T. and M. Purvis, "REP 103: Standard Units of
Measure and Coordinate Conventions", 7 October 2010,
<https://www.ros.org/reps/rep-0103.html>.
[RFC8792] Watsen, K., Auerswald, E., Farrel, A., and Q. Wu,
"Handling Long Lines in Content of Internet-Drafts and
RFCs", RFC 8792, DOI 10.17487/RFC8792, June 2020,
<https://www.rfc-editor.org/rfc/rfc8792>.
[SKOS] World Wide Web Consortium, "SKOS Simple Knowledge
Organization System Reference", n.d.,
<https://www.w3.org/TR/skos-reference/>.
[SNOMED-CT]
SNOMED International, "SNOMED CT", n.d.,
<https://www.snomed.org/>.
[SOSA-SSN] World Wide Web Consortium, "Semantic Sensor Network
Ontology", n.d., <https://www.w3.org/TR/vocab-ssn/>.
Vasters Expires 7 February 2027 [Page 131]
Internet-Draft JSON Structure Semantic Annotations August 2026
[SPASE] SPASE Consortium, "Space Physics Archive Search and
Extract (SPASE) Data Model, Version 2.7.2", 2026,
<https://spase-group.org/data/model/spase-latest/
index.html>.
[SSC-COORDS]
NASA Goddard Space Flight Center, "Satellite Situation
Center Users Guide, Appendix C: Description of Selected
Coordinate Systems", n.d.,
<https://sscweb.gsfc.nasa.gov/users_guide/
Appendix_C.html>.
[UNLOCODE] United Nations Economic Commission for Europe, "UN/LOCODE:
United Nations Code for Trade and Transport Locations",
n.d., <https://unece.org/trade/cefact/unlocode-code-list-
country-and-territory>.
[UNSPSC] United Nations Global Marketplace, "United Nations
Standard Products and Services Code (UNSPSC)", n.d.,
<https://www.ungm.org/Public/UNSPSC>.
[USGS-LANDSAT]
United States Geological Survey, "What are the band
designations for the Landsat satellites?", n.d.,
<https://www.usgs.gov/faqs/what-are-band-designations-
landsat-satellites>.
[USGS-LANDSAT-L1]
United States Geological Survey, "Using the USGS Landsat
Level-1 Data Product", n.d., <https://www.usgs.gov/
landsat-missions/using-usgs-landsat-level-1-data-product>.
[WHO-ATC] WHO Collaborating Centre for Drug Statistics Methodology,
"ATC/DDD Index", n.d.,
<https://atcddd.fhi.no/atc_ddd_index/>.
[WHO-ICD] World Health Organization, "International Classification
of Diseases (ICD)", n.d., <https://icd.who.int/>.
[WMO-CODES]
World Meteorological Organization, "WMO Codes Registry
(WMO No. 306 Manual on Codes)", n.d.,
<https://codes.wmo.int/>.
Vasters Expires 7 February 2027 [Page 132]
Internet-Draft JSON Structure Semantic Annotations August 2026
[WSDOT-LRS]
Washington State Department of Transportation, "State
Route Linear Referencing System", n.d.,
<https://data.wsdot.wa.gov/arcgis/rest/services/Shared/
LRSData/FeatureServer/9>.
Appendix A. Reference URIs (Informative)
The URIs below illustrate the kind values defined in this document.
None of these lists is exhaustive, and a publisher can supersede any
definition.
A.1. Vocabularies
A reference identifies a term, not the namespace of the model that
defines it; Section 4.1 names the model behind each kind.
Vocabularies that define terms in those models and that are widely
used with observation data include the Semantic Sensor Network
ontology [SOSA-SSN], which publishes http://www.w3.org/ns/sosa/ and
http://www.w3.org/ns/ssn/, and the Provenance Ontology [PROV-O],
which publishes http://www.w3.org/ns/prov#.
A.2. Temporal Reference Systems
The URIs in this section resolve at the OGC definitions server.
Time-scale concepts, for kind ogc-trs:
* http://www.opengis.net/def/trs/BIPM/0/UTC, Coordinated Universal
Time;
* http://www.opengis.net/def/trs/BIPM/0/TAI, International Atomic
Time;
* http://www.opengis.net/def/trs/IERS/0/UT1, Universal Time UT1; and
* http://www.opengis.net/def/trs/USNO/0/GPS, GPS Time.
None of these constrains the type of the annotated value. Each names
a time scale and establishes no axis, unit, or encoding, so any of
them can accompany a Core temporal type, a string, a numeric epoch
count, or a compound position.
Temporal coordinate reference systems, for kind ogc-temporal-crs.
Each establishes an origin and an axis, and the axis constrains the
annotated type:
Vasters Expires 7 February 2027 [Page 133]
Internet-Draft JSON Structure Semantic Annotations August 2026
* http://www.opengis.net/def/crs/OGC/0/GregorianDateTime, a date and
time in the Gregorian calendar. Its axis carries no unit, and it
takes a Core datetime, date, or time, or a string in the same
form.
* http://www.opengis.net/def/crs/OGC/0/UnixTime, seconds elapsed
from 1970-01-01T00:00:00Z. It takes an integer or number carrying
UCUM s.
* http://www.opengis.net/def/crs/OGC/0/AnsiDate, days elapsed from
1601-01-01T00:00:00Z. It takes an integer or number carrying UCUM
d.
* http://www.opengis.net/def/crs/OGC/0/JulianDate, days elapsed from
the Julian period origin. It takes a number carrying UCUM d,
since its origin falls at noon and positions are ordinarily
fractional.
* http://www.opengis.net/def/crs/OGC/0/TruncatedJulianDate, days
elapsed from 1968-05-24T00:00:00Z. It takes a number carrying
UCUM d.
* http://www.opengis.net/def/crs/OGC/0/BeforePresentTime, years
counted backwards from 1950. It takes a number carrying UCUM a.
* http://www.opengis.net/def/crs/OGC/0/ChronometricGeologicTime,
millions of years counted backwards from year zero. It takes a
number carrying UCUM Ma.
None of the numeric definitions takes a string, and GregorianDateTime
does not take a number. The last two count backwards, so a larger
value is an earlier position and sortOrder is backward.
The register also serves a parameterized definition taking an origin
and a unit, which covers epoch counts for which no named definition
exists. A count of milliseconds from the Unix origin is identified
by:
http://www.opengis.net/def/crs/OGC/0/Temporal
?epoch=%221970-01-01T00:00:00Z%22&uom=%22ms%22
Parameter values are quoted, and the URI is one line. The constraint
follows the uom parameter: this URI takes an integer or number
carrying UCUM ms. A count of seconds from the same origin is a
different definition, not the same definition read at a different
scale.
Vasters Expires 7 February 2027 [Page 134]
Internet-Draft JSON Structure Semantic Annotations August 2026
A.3. Coordinate Reference Systems
For kind ogc-crs:
* http://www.opengis.net/def/crs/OGC/1.3/CRS84, WGS 84 with axes
longitude, latitude;
* http://www.opengis.net/def/crs/OGC/0/CRS84h, WGS 84 with axes
longitude, latitude, ellipsoidal height;
* http://www.opengis.net/def/crs/EPSG/0/4326, WGS 84 with axes
latitude, longitude;
* http://www.opengis.net/def/crs/EPSG/0/4979, WGS 84 with axes
latitude, longitude, ellipsoidal height.
Axis order differs among these definitions, and the definition
establishes it. The first two and the last two describe the same
datum in opposite axis order.
For kind epsg, the EPSG Geodetic Parameter Dataset serves its own
records, for example https://apps.epsg.org/api/v1/CoordRefSystem/4326
[EPSG]. A definition served at an OGC URI under an EPSG code, as in
the list above, is ogc-crs rather than epsg.
A.4. Vector Reference Frames
No register of vector reference frames corresponds to the temporal
and coordinate registers. A registered coordinate reference system
whose axes are directions may be cited with ogc-crs or epsg, and the
URIs listed in Appendix A.3 apply unchanged. Most frames in which
vector quantities are reported are not registered at all.
Some communities publish a closed list of frame _names_ without
serving a URI per frame. The SPASE data model [SPASE] is the case in
point: its CoordinateSystemName enumeration fixes tokens such as GSE,
GSM, GEI, SM, RTN, HEE, MFA, and SensorCoordinates, and defines what
each one means, but the register itself carries no per-token
reference URI. A token from such a list is not a reference value.
Where the community that publishes the list also serves a resolvable
definition, that URI is the reference and the token is not; where it
does not, the frame is written as a tuple meta-type in the schema
document and cited with kind type, as in Section 10.2.
Vasters Expires 7 February 2027 [Page 135]
Internet-Draft JSON Structure Semantic Annotations August 2026
A.5. Linear Reference Systems
No register of linear reference systems corresponds to the temporal
and coordinate registers. ISO 19148 [ISO19148] specifies the
conceptual schema, in which a location is a measurement along a
linear element and optionally an offset from it, so that overlapping
attributes can be carried against one geometry without fragmenting
it. It defines no identifiers for individual systems. A linear
reference system is therefore published by the authority that
maintains the network, which is why lrs-network is the value defined
here for a published system, and why a system published in another
form is identified by a value naming the model that publishes it. A
system that no authority publishes is defined as a meta-type in the
schema and cited with type.
In the United States, the FHWA ARNOLD directive [FHWA-ARNOLD]
requires each state department of transportation to maintain one
linear reference system covering all public roads, modelled as the
HPMS Field Manual prescribes [FHWA-HPMS]: routes carrying measure
values on their vertices, with attributes held in event tables that
cite a route and a measure rather than segmenting the underlying
geometry. A service published under that directive is an lrs-
network, and its layer and metadata resources establish the linear
elements and the measure. The Washington state route network used in
Section 10.5 is served at
https://data.wsdot.wa.gov/arcgis/rest/services/Shared/LRSData/
FeatureServer/9 [WSDOT-LRS].
A.6. Code Lists
A reference identifies one specific code list, and kind classifies
the register model that list belongs to (Section 6.1). The registers
fall into two tiers by how a reference behaves.
Some publish a resolvable URI for the list, or for each entry, so
that a reference both identifies and dereferences:
* wmo-codes: a register in the WMO Codes Registry, such as
http://codes.wmo.int/bufr4/codeflag/0-20-003, the present-weather
register, whose entries are served beneath it [WMO-CODES].
* iana: a registry served under https://www.iana.org/assignments/,
such as https://www.iana.org/assignments/media-types/media-
types.xhtml for media types, or https://www.iana.org/assignments/
language-subtag-registry for the BCP 47 language subtags
[IANA-PROTOCOLS] [IANA-LANGTAGS].
Vasters Expires 7 February 2027 [Page 136]
Internet-Draft JSON Structure Semantic Annotations August 2026
* snomed-ct: an edition under the SNOMED CT URI scheme,
http://snomed.info/sct for the International Edition, with a
module or version appended for a specific release [SNOMED-CT].
* loinc: the LOINC code system, http://loinc.org [LOINC].
* icd: a WHO linearization, http://id.who.int/icd/release/11/mms for
the ICD-11 mortality and morbidity statistics [WHO-ICD].
The rest publish their lists in standards or directories that mint no
per-list machine URI. A reference to one identifies more often than
it resolves, and names the standard's identifier or landing page:
* iso: an ISO code table, named by its catalogue page such as
https://www.iso.org/iso-3166-country-codes.html, or by a standard
URN such as urn:iso:std:iso:3166:-1 [ISO3166] [ISO4217] [ISO639].
* unlocode: https://unece.org/trade/cefact/unlocode-code-list-
country-and-territory [UNLOCODE].
* icao: the location indicators of Doc 7910,
https://store.icao.int/en/location-indicators-doc-7910, or the
aircraft type designators of Doc 8643, https://www.icao.int/
operational-safety/doc-8643-aircraft-type-designators [ICAO7910]
[ICAO8643].
* iata: https://www.iata.org/en/publications/directories/code-
search/ [IATA-CODES].
* atc: https://atcddd.fhi.no/atc_ddd_index/ [WHO-ATC].
* unspsc: https://www.ungm.org/Public/UNSPSC [UNSPSC].
A processor is not required to dereference a reference of either
tier, and an unresolved reference is indeterminate rather than
incorrect. Under kind type the list is a meta-type in the schema and
reference is the type reference { "$ref": <JSON Pointer> }, not a
URI.
Change Log
* Initial version.
Acknowledgments
The author thanks the JSON Structure community for review and
feedback.
Vasters Expires 7 February 2027 [Page 137]
Internet-Draft JSON Structure Semantic Annotations August 2026
Author's Address
Clemens Vasters
Microsoft Corporation
Email: clemensv@microsoft.com
Vasters Expires 7 February 2027 [Page 138]