Read and validate JSON-LD¶
Taking a document you did not write. The connectors will happily import it and hand you back model objects — but they will not tell you it was wrong. This guide covers what you get, what you lose, and where you have to check things yourself.
Import returns an array, always¶
const objects = c.import(jsonld);
for (const o of objects) {
console.log(o.semanticType, o.semanticId);
}
Even for a single-node document. The shape of the input does not change the shape of the return, so you never need to special-case it:
| Input | import() returns |
|---|---|
One node, no @graph |
1-element array |
One node in a @graph |
1-element array |
| Many nodes | N-element array |
| Empty | empty array |
Identify nodes by @id¶
There is no getByType helper. Build your own index — it is the pattern the
tutorials use and the one the conformance suite checks:
const byId = new Map(objects.map(o => [o.semanticId, o]));
const farm = byId.get("https://example.com/farm/1");
import() also accepts an already-parsed object, so you do not have to
JSON.parse first:
What you cannot rely on¶
Unknown types are skipped, not reported¶
A @type with no matching DFC class does not raise. The node is dropped and
you get a shorter array:
const objects = c.import({ "@id": "https://x/1", "@type": "dfc-b:NotAThing" });
objects.length; // 0
Check the length. If you expect N nodes and get fewer, that is your only signal. Compare against the input:
const expected = (input["@graph"] ?? [input]).length;
if (objects.length !== expected) {
throw new Error(`dropped ${expected - objects.length} node(s)`);
}
Unknown predicates are dropped¶
Predicates the model does not declare are discarded and do not come back on re-export. This is lossy and it is the same in all three connectors:
const input = {
"@id": "https://x/1", "@type": "dfc-b:Organization",
"dfc-b:name": "Acme",
"https://your.org/internal-id": "SKU-1", // gone
};
const [org] = c.import(input);
await c.export(org); // no "https://your.org/internal-id"
If your own terms are mixed into the document, capture them before importing. You cannot get them back out through the connector.
The full rule — including that deprecated properties are kept, and that known properties on the wrong class are dropped — is in property retention.
References resolve only within the document¶
A property pointing at an @id present in the same document comes back as
the model instance. One that is not present comes back as a string:
const [product, org] = c.import(closedGraph);
product.suppliedBy === org; // true: target was in the document
const [orphan] = c.import(openGraph);
typeof orphan.suppliedBy; // "string": target was not
So the same property has two possible types depending on the input. If you need the object, make sure the graph is closed.
Nothing is checked¶
No type, range, cardinality, or vocabulary check happens. A dfc-b:hasUnit
of dfc-m:NotAUnit imports and re-exports cleanly. A dfc-b:value of
"not a number" does too.
The validation concept page explains why the connectors are built this way and where the four levels of validation actually stand. In short: only SHACL ships.
Legacy documents¶
dfc-b:Enterprise is mapped to dfc-b:Organization on import, following the
DFC v2.0 rename:
const [org] = c.import({ "@id": "https://x/1", "@type": "dfc-b:Enterprise" });
org.semanticType; // "dfc-b:Organization"
This is one-way. You cannot export an Enterprise.
What to check yourself¶
In rough order of value:
- Node count. Compare input and output lengths. Catches unknown types.
- Round-trip fidelity. Re-export and diff, ignoring key order. Catches dropped predicates and shape changes.
- Your own business rules. Prices positive, dates ordered, references resolvable.
- SHACL, if you need cross-node constraints. The shapes are in
shacl/; see validation.
A minimal guard, before you trust an import:
function importStrict(c: Connector, input: unknown): SemanticObject[] {
const objects = c.import(input as Record<string, unknown>);
const expected = ((input as any)["@graph"] ?? [input]).length;
if (objects.length !== expected) {
throw new Error(`import dropped ${expected - objects.length} of ${expected} nodes`);
}
return objects;
}
See also¶
- Validation — the four levels, what ships
- Identifiers — choosing
@ids for what you emit - JSON-LD round trip — the executed tutorial