Skip to main content

SDIF to JSON

The sdif to-json command converts an SDIF document to JSON, writing the result to stdout.

sdif to-json <path>

Input: A .sdif source file.

Output: JSON written to stdout.

To save the result:

sdif to-json plan.sdif > plan.json

How SDIF maps to JSON

The output is a single JSON object. Each kind of SDIF content maps to a key in that object.

Scalar fields

Each key value statement in the SDIF document becomes a top-level key in the JSON object:

@sdif 1.0

title "Q3 Plan"
status active
revision 2

Becomes:

{
"title": "Q3 Plan",
"status": "active",
"revision": "2"
}

All values are emitted as JSON strings. SDIF has no numeric or boolean literal types, so 2 in SDIF becomes the string "2" in JSON, not the number 2.

The kind field

If the document contains a kind declaration, it is emitted as a top-level "kind" string key:

kind ProjectPlan

Becomes:

{
"kind": "ProjectPlan"
}

Tables

Each SDIF table block becomes a JSON array of objects under the same key. Column names become the keys of each object:

tasks[id,name,status]:
T1 Research done
T2 Draft open

Becomes:

{
"tasks": [
{"id": "T1", "name": "Research", "status": "done"},
{"id": "T2", "name": "Draft", "status": "open"}
]
}

Relations

A rel: block becomes a JSON array under a "relations" key. Each triple is emitted as a three-element array [subject, predicate, object]:

rel:
T1 blocks T2
T2 requires M1

Becomes:

{
"relations": [
["T1", "blocks", "T2"],
["T2", "requires", "M1"]
]
}

Concrete example

Input — plan.sdif:

@sdif 1.0

kind ProjectPlan

title "Website Relaunch"
owner Alice

milestones[id,name,due]:
M1 "Design complete" 2026-06-01
M2 "Beta launch" 2026-07-15

rel:
M1 precedes M2

Command:

sdif to-json plan.sdif

Output:

{
"kind": "ProjectPlan",
"title": "Website Relaunch",
"owner": "Alice",
"milestones": [
{"id": "M1", "name": "Design complete", "due": "2026-06-01"},
{"id": "M2", "name": "Beta launch", "due": "2026-07-15"}
],
"relations": [
["M1", "precedes", "M2"]
]
}

Known limitations

Canonical form and hash are not preserved

The JSON output carries the document's logical content but not its canonical byte form. If you need a stable identifier, compute the hash before converting:

sdif hash plan.sdif
sdif to-json plan.sdif > plan.json

Rules blocks are not represented

SDIF supports constraint rules in schema documents. Rules blocks have no JSON representation and are not included in the output.

Schema and directive metadata

The @sdif 1.0 header directive is not emitted as a JSON key. If the document contains additional directives, they may appear under a top-level "_directives" key, but this behavior is implementation-defined. Do not rely on it for programmatic use.

All values are strings

SDIF values are untyped by default. sdif to-json emits all scalar values as JSON strings. If downstream consumers require typed values (e.g. a number or boolean), you will need to coerce them after conversion.

AI projections

.sdif.ai projection files can be passed to sdif to-json. The converter first expands any grouped relations and alias mappings before emitting JSON, so the output reflects the full canonical content, not the compact projection form.


Round-trip expectations

Converting SDIF to JSON and back with sdif from-json is not fully lossless. Expect the following:

ContentSurvives round-trip?
Scalar fieldsYes
Tables (uniform column structure)Yes (column order may vary)
kind declarationNo — from-json does not emit kind
rel: blocksNo — relations become a flat array in JSON; from-json treats that array as a table, not a rel: block
Canonical hashNo — source formatting differs
All-string valuesYes

If you need to move data between systems and preserve SDIF semantics, pass the .sdif file directly rather than routing through JSON.


Next steps