diff --git a/docs/rules.md b/docs/rules.md index 50ee93a..fb38cd4 100644 --- a/docs/rules.md +++ b/docs/rules.md @@ -933,6 +933,23 @@ See [this rule in the specification](spec/#OOLD-VER-edb9) (section: identificati ## EXT - Standard extensions (JSON-LD and JSON Schema) +### OOLD-EXT-05d3 + +- Level: MUST NOT +- Applies to: implementation +- Machine-checkable: no +- Since: 1.0.0-rc.3 + +A frame derivation must not emit a subframe for a property whose key aliases a JSON-LD keyword. + +A derivation MUST NOT emit a subframe for a property whose key aliases a JSON-LD keyword - conventionally `id` for `@id` and `type` for `@type` (see [identity](spec/#identity)). + +??? quote "In context" + + A derivation MUST recognize a property as reference-valued from any of three signals: an [`x-oold-range`](spec/#range-of-properties) on a string-typed value, an IRI-family `format` (the family [range-reference-form](spec/#range-reference-form) recommends), or a `@context` term mapped `"@type": "@id"`. Where a property matches both this and the embedded-object shape, the embedded-object reading MUST win: a property whose value is an object is an embed whatever its term declares. A derivation MUST NOT emit a subframe for a property whose key aliases a JSON-LD keyword - conventionally `id` for `@id` and `type` for `@type` (see [identity](spec/#identity)). Such a key names the node rather than pointing at another one, and a subframe under it produces `{"@id": {...}}`, which a processor rejects. + +See [this rule in the specification](spec/#OOLD-EXT-05d3) (section: framing). + ### OOLD-EXT-1dc8 - Level: MUST NOT @@ -1211,6 +1228,23 @@ A tool that derives a frame MUST derive it mechanically: the schema's class type See [this rule in the specification](spec/#OOLD-EXT-68fa) (section: framing). +### OOLD-EXT-6d10 + +- Level: MUST +- Applies to: implementation +- Machine-checkable: no +- Since: 1.0.0-rc.3 + +A frame derivation recognizes a property as reference-valued from x-oold-range, an IRI-family format, or a term mapped @type @id. + +A derivation MUST recognize a property as reference-valued from any of three signals: an [`x-oold-range`](spec/#range-of-properties) on a string-typed value, an IRI-family `format` (the family [range-reference-form](spec/#range-reference-form) recommends), or a `@context` term mapped `"@type": "@id"`. + +??? quote "In context" + + A derivation MUST recognize a property as reference-valued from any of three signals: an [`x-oold-range`](spec/#range-of-properties) on a string-typed value, an IRI-family `format` (the family [range-reference-form](spec/#range-reference-form) recommends), or a `@context` term mapped `"@type": "@id"`. Where a property matches both this and the embedded-object shape, the embedded-object reading MUST win: a property whose value is an object is an embed whatever its term declares. A derivation MUST NOT emit a subframe for a property whose key aliases a JSON-LD keyword - conventionally `id` for `@id` and `type` for `@type` (see [identity](spec/#identity)). Such a key names the node rather than pointing at another one, and a subframe under it produces `{"@id": {...}}`, which a processor rejects. + +See [this rule in the specification](spec/#OOLD-EXT-6d10) (section: framing). + ### OOLD-EXT-6ea3 - Level: SHOULD @@ -1249,6 +1283,23 @@ By default a converter co-emits only `skos:exactMatch` entries; entries whose `p See [this rule in the specification](spec/#OOLD-EXT-7256) (section: synonyms). +### OOLD-EXT-725f + +- Level: MUST +- Applies to: implementation +- Machine-checkable: no +- Since: 1.0.0-rc.3 + +Framing a graph that holds several nodes matching a derived frame yields one instance document per match. + +Framing a graph with a schema-derived frame MUST yield one instance document per matching node, delivered as a `@graph` of matches rather than an arbitrary single root. + +??? quote "In context" + + Framing a graph with a schema-derived frame MUST yield one instance document per matching node, delivered as a `@graph` of matches rather than an arbitrary single root. Dually, several instance documents - each expanded through its own `$schema` - merge into one graph, because expansion assigns every node its own IRI and identical IRIs denote the same node. + +See [this rule in the specification](spec/#OOLD-EXT-725f) (section: framing-many-documents). + ### OOLD-EXT-7c5d - Level: MUST @@ -1467,3 +1518,20 @@ A property coerced `"@type": "@vocab"` therefore SHOULD constrain its values wit Because `@vocab` expands an unmatched string against the vocabulary - concatenating it onto the default vocabulary base when one is set (minting a new IRI), or leaving it a relative IRI when none is - a typo silently becomes a stray IRI rather than an error. A property coerced `"@type": "@vocab"` therefore SHOULD constrain its values with an `enum` of the value terms (optionally named with `x-enum-varnames`) or with `x-oold-range`, so only intended individuals are accepted. The value terms SHOULD also be kept from colliding with JSON-LD keyword aliases (`id`, `type`) or other context terms, since a value term shares the context's global term namespace - a term added for a value would otherwise also rewrite a property or keyword of the same name. Confining the value terms to the property's own scoped `@context` keeps them out of that shared namespace, since they then resolve only for that property's values; naming them with opaque identifiers such as UUIDs avoids the clash where readability is not required. See [this rule in the specification](spec/#OOLD-EXT-fdd8) (section: value-term-aliases). + +### OOLD-EXT-ff64 + +- Level: MUST +- Applies to: implementation +- Machine-checkable: no +- Since: 1.0.0-rc.3 + +Where a property matches both the embedded-object and the reference-valued signals, the embedded-object reading wins. + +Where a property matches both this and the embedded-object shape, the embedded-object reading MUST win: a property whose value is an object is an embed whatever its term declares. + +??? quote "In context" + + A derivation MUST recognize a property as reference-valued from any of three signals: an [`x-oold-range`](spec/#range-of-properties) on a string-typed value, an IRI-family `format` (the family [range-reference-form](spec/#range-reference-form) recommends), or a `@context` term mapped `"@type": "@id"`. Where a property matches both this and the embedded-object shape, the embedded-object reading MUST win: a property whose value is an object is an embed whatever its term declares. A derivation MUST NOT emit a subframe for a property whose key aliases a JSON-LD keyword - conventionally `id` for `@id` and `type` for `@type` (see [identity](spec/#identity)). Such a key names the node rather than pointing at another one, and a subframe under it produces `{"@id": {...}}`, which a processor rejects. + +See [this rule in the specification](spec/#OOLD-EXT-ff64) (section: framing). diff --git a/docs/spec/index.html b/docs/spec/index.html index b044b09..b345417 100644 --- a/docs/spec/index.html +++ b/docs/spec/index.html @@ -912,6 +912,8 @@

Terminology

Framing

JSON-LD 1.1 Framing reshapes a flat or arbitrarily-structured RDF graph into a specific tree layout described by a frame. An OO-LD schema already describes exactly such a tree - its properties give the nesting, its @context gives the term IRIs, a type constant (x-oold-instance-rdf-type, or a const on the type property) gives the node type, and x-oold-range gives the type of embedded or referenced objects - so an OO-LD-aware tool MAY auto-construct a frame from the schema. Framing an instance graph with that frame produces a JSON document shaped like the schema, which then validates against the same schema.

This makes an OO-LD schema bidirectional: its @context drives expansion (JSON to RDF), and the frame derived from its structure drives framing (RDF back to the schema's JSON tree). A tool that derives a frame MUST derive it mechanically: the schema's class type becomes the frame @type; an inlined object property becomes a nested subframe that embeds the referenced node; a reference-valued property (including one whose term is mapped with JSON-LD @reverse) becomes a subframe with @embed: @never so its targets stay IRIs, in line with the inline-versus-reference choice x-oold-range already records; and @explicit / @requireAll / @default follow from additionalProperties and required. The frame's @context is the composition of the referenced schemas' contexts.

+

A derivation MUST recognize a property as reference-valued from any of three signals: an x-oold-range on a string-typed value, an IRI-family format (the family recommends), or a @context term mapped "@type": "@id". Where a property matches both this and the embedded-object shape, the embedded-object reading MUST win: a property whose value is an object is an embed whatever its term declares. A derivation MUST NOT emit a subframe for a property whose key aliases a JSON-LD keyword - conventionally id for @id and type for @type (see ). Such a key names the node rather than pointing at another one, and a subframe under it produces {"@id": {...}}, which a processor rejects.

+

Omitting @embed: @never is not a cosmetic difference. A reference whose target happens to carry triples in the same graph is then embedded as an object, and the framed document no longer validates against the schema the frame was derived from, which declares a string in that position.

-

Framing is not the only option for this transformation. When the source data lives in a triplestore or behind a SPARQL endpoint, a SPARQL CONSTRUCT query - also derivable from the schema - can select and reshape the relevant subgraph directly, including deriving reverse relations such as employees from the inverse of schema:worksFor; compacting that result with the schema's @context (and framing it where nesting is required) yields the same OO-LD instance.

JSON Schema

OO-LD targets [[JSONSCHEMA]] (2020-12) as its normative dialect. An OO-LD schema SHOULD declare the OO-LD dialect meta-schema (which extends 2020-12) as its $schema, e.g. "$schema": "https://oo-ld.org/latest/meta/oold-meta-schema.json" - pinning a specific version (e.g. .../0.4.0/meta/oold-meta-schema.json) for reproducibility. Declaring the plain 2020-12 meta-schema (https://json-schema.org/draft/2020-12/schema) remains valid for tools that only understand standard JSON Schema.

+
Many documents, one graph

The example above frames a graph that happens to hold one matching node. In general a graph holds many, and the relationship runs in both directions.

+

Framing a graph with a schema-derived frame MUST yield one instance document per matching node, delivered as a @graph of matches rather than an arbitrary single root. Dually, several instance documents - each expanded through its own $schema - merge into one graph, because expansion assigns every node its own IRI and identical IRIs denote the same node.

+

The @embed: @never derivation is what keeps the two directions consistent. A reference that stays a reference belongs to exactly one document: the one describing the node it is stored on. If framing embedded it instead, the target's triples would be copied into every document that references it, so a node's description would depend on which document a reader happened to open, and merging the documents back would re-assert those triples from several places at once. Keeping references as IRIs means each document round-trips independently and their union is the graph they came from.

+

This is the framing-based answer to the object-graph mapping question: a schema does not describe a document in isolation, it describes how to cut one document out of a graph and how to put it back.

+

Framing is not the only option for this transformation. When the source data lives in a triplestore or behind a SPARQL endpoint, a SPARQL CONSTRUCT query - also derivable from the schema - can select and reshape the relevant subgraph directly, including deriving reverse relations such as employees from the inverse of schema:worksFor; compacting that result with the schema's @context (and framing it where nesting is required) yields the same OO-LD instance.

JSON Schema

OO-LD targets [[JSONSCHEMA]] (2020-12) as its normative dialect. An OO-LD schema SHOULD declare the OO-LD dialect meta-schema (which extends 2020-12) as its $schema, e.g. "$schema": "https://oo-ld.org/latest/meta/oold-meta-schema.json" - pinning a specific version (e.g. .../0.4.0/meta/oold-meta-schema.json) for reproducibility. Declaring the plain 2020-12 meta-schema (https://json-schema.org/draft/2020-12/schema) remains valid for tools that only understand standard JSON Schema.

2020-12 is REQUIRED, not merely preferred: OO-LD's composition places $ref alongside sibling keywords (e.g. a property carrying type, x-oold-range and @context, or allOf: [{$ref: ...}] next to properties). Keywords adjacent to $ref are only evaluated from JSON Schema 2019-09 onward; in Draft 4 and Draft 7 they are ignored ([[JSONSCHEMA]] ยง8.2.3.1). Keywords such as const (used throughout this document) are likewise only available from draft-06 onward. Migration from the earlier Draft-4-style notation: rename definitions to $defs, id to $id, and use the numeric form of exclusiveMinimum/exclusiveMaximum instead of the boolean form.

Enum names and descriptions

An enum constrains a property to a fixed set of values. Those values are data, chosen for what they mean on the wire, so they are routinely not usable as identifiers in generated code: an IRI, a CURIE, a value carrying spaces or hyphens, or a number. Two established vendor extensions carry the missing information, each a list positionally aligned with enum: