Skip to content

Tooling

Because OO-LD documents are ordinary JSON Schema and JSON-LD, the full ecosystem of both standards applies. The lists below collect generic tooling, OO-LD-specific implementations, and interactive playgrounds.

General

OO-LD Specific

Playgrounds

Validation and test suites

The oold-schema repository ships a validation harness (scripts/validate.mjs) with two tiers. Run both with make validate, or make check (which also re-renders the spec and builds the site); CI runs make check on every push.

General workflow (any schema, no fixtures)

These run on every schema and instance in examples/ with no per-schema test data, so they apply to any OO-LD schema you write. They are also reusable on your own schemas: the harness is exposed as an oold-validate CLI, so a downstream repo can conformance-check its generated schemas against this exact pipeline without copying it -

npx --yes github:OO-LD/oold-schema oold-validate path/to/schemas

Given a directory argument, oold-validate <dir> runs only the general-workflow tier below (well-formedness, auto-generated instance, branch iteration, RDF roundtrip, pattern lint) over that directory's *.schema.json, using this package's meta-schemas; the deterministic per-feature suites and vocabulary coverage stay scoped to this repo's own examples/. The checks are:

  • Well-formedness - the schema validates against the OO-LD meta-schema and its $ref composition resolves.
  • Auto-generated instance - an instance is generated (via json-schema-faker, all properties, declared formats respected) and must validate against the schema; this catches unsatisfiable schemas.
  • Branch iteration - each oneOf / anyOf branch is pinned in turn and an instance generated for it, exercising every variant deterministically.
  • RDF roundtrip - each instance is converted instance -> RDF -> instance. It fails if a property is lost (the @context does not map it) or if the reconstruction no longer validates against its schema (the @context did not preserve a property's shape - for example a strict type: array property whose single-element array came back as a scalar).
  • Pattern lint - each schema's @context is checked for round-trip-safe patterns. Errors (MUST): a term must not coerce a literal to a datatype JSON-LD produces by default from a native JSON value ("@type": "xsd:string", xsd:boolean, xsd:integer, xsd:double - none of them round-trip: xsd:string is elided from plain literals and boolean/integer/double literals reconstruct as untyped native JSON values, so the coercing term is never selected on the way back; non-default datatypes such as xsd:date or xsd:float coerce fine), and a strictly type: array property must declare "@container": "@set" (or "@list"), or a single-element array returns as a scalar and fails re-validation. A cardinality-flexible property (a oneOf/anyOf of a literal and an array) MAY declare it but need not. Warning (SHOULD): a bare-IRI-string reference that lacks an iri-reference (or stricter uri*) format - the reference still round-trips, so a lexical format is only recommended.

Note on cyclic scoped contexts: a property that embeds an object carries a scoped @context referencing the embedded type's context; these references form an embed graph. When that graph has a cycle (a type embedding itself, or two types embedding each other), a JSON-LD processor must eagerly validate the recursive scoped context. The spec bounds this, but neither jsonld.js 8.3.3 (heap exhaustion) nor PyLD 3.1.0 (recursion error) honors the bound, so such a schema is not round-trippable in practice. The harness detects schemas that reach a scoped-context cycle and skips their round-trip with a warning (the meta-schema and pattern-lint checks still run) rather than crashing. Model cyclic or independent-entity edges as references (@type: "@id" + x-oold-range, no scoped context); a self-reference through the top-level context is fine. See the specification's Projection to RDF and round-trip.

Note on IRI formats: iri and iri-reference are provided by the ajv-formats-draft2019 plugin, whose regexes are currently buggy - they reject valid compact IRIs such as ex:alice and are even mutually inconsistent (iri accepts urn:uuid:..., iri-reference does not). Because a compact IRI is a valid IRI (RFC 3987 - an IRI is a superset of a URI), the harness overrides these two format checks with conformant implementations. If you validate OO-LD schemas with your own ajv setup, apply the same override until the plugin is fixed (upstream bug).

Deterministic per-feature suites

Precise fixtures with exact expected outcomes live in examples/compliance/:

  • Vocabulary well-formedness (oold-vocab.json) - candidate schemas checked against the meta-schema, asserting each x-oold-* / x-oold-ui-* keyword is accepted when well-formed and rejected when malformed. A coverage cross-check reads the keyword list from the meta-schemas and fails if any keyword is untested, keeping the suite in sync with them.
  • OO-LD JSON-LD constructs (jsonld-features.json) - only the constructs OO-LD adds on top of plain JSON-LD (base-class @context inheritance, property-$ref scoped contexts), not vanilla JSON-LD. Each case merges the JSON Schema Test Suite shape (valid) with the JSON-LD Test Suite shape (expectRdf, compared by RDF dataset isomorphism; expectErrorCode for negatives).

To extend it: add a case to oold-vocab.json whenever you add a meta-schema keyword (the coverage check will otherwise fail), or add an examples/compliance/<feature>.json group that names an example schema via schemaRef and asserts valid / expectRdf per instance.

OO-LD semantic behaviour that a validator and a JSON-LD processor cannot check on their own - x-oold-range enforcement, composition merge and most-derived-wins override, x-oold-ref resolution - is a conformance target for the oold library and reuses the same fixture format.