Skip to content

3. Logical structure

Contents of DID 0.2

Independently of format and file split, a definition has this logical structure (JSON Schema: did.schema.json, $defs/Definition):

{
  "$schema": "https://etalii.net/adp/did/schema/0.2/did.schema.json#/$defs/Definition",
  "did": "0.2",
  "language": { "id": "org.example.statemachine", "version": "1.2.0" },
  "meta": {
    "createdAt": "2026-09-25T20:14:03Z",
    "modifiedAt": "2026-09-26T08:00:00Z",
    "generator": "Acme Diagrams 4.2"
  },
  "diagram": { "attributes": { "title": "Door controller" } },
  "elements": [
    { "id": "st_01J8Z3…", "type": "InitialState" },
    { "id": "st_01J8Z4…", "type": "State", "attributes": { "name": "Closed" } },
    { "id": "st_01J8Z5…", "type": "State", "attributes": { "name": "Open", "entryAction": "light.on()" } }
  ],
  "relations": [
    { "id": "tr_01J8Z6…", "type": "Transition", "source": "st_01J8Z4…", "target": "st_01J8Z5…",
      "attributes": { "trigger": "open" } }
  ],
  "views": [
    {
      "id": "v_main", "viewpoint": "main",
      "viewport": { "x": 0, "y": 0, "zoom": 1 },
      "nodes": {
        "st_01J8Z3…": { "x": 40,  "y": 60,  "w": 20,  "h": 20 },
        "st_01J8Z4…": { "x": 120, "y": 40,  "w": 120, "h": 60 },
        "st_01J8Z5…": { "x": 340, "y": 40,  "w": 120, "h": 60, "style": { "fill": "#EAF3DE" } }
      },
      "edges": {
        "tr_01J8Z6…": { "waypoints": [], "labels": { "trigger": { "dx": 0, "dy": -6 } } }
      }
    }
  ],
  "suppressions": [],
  "extensions": {}
}

Element record (elements[]):

Property Type Description
id string Required, unique within the definition.
type string Required, a concrete node type (qualified by import alias if imported).
attributes object Stored attribute values (omitting unset and, if omitDefaults, default values). Attribute values follow DISL 4.2 representations; references are ids.
parent id Containing element (omitted for top-level).
slot string Slot within the parent (DISL 4.8).
order int or string Position among siblings when children.ordered (fractional-index strings are RECOMMENDED for collaboration: "a0", "a0V").
ports {id, type, attributes}[] Port instances. type is the port name ("in").
x-* Extensions.

Nesting is expressed by parent, not by physical nesting, so moving an element between containers changes one line. Runtimes MAY offer a nested pretty-print as an alternative layout: "nested", but the flat form is canonical.

Attribute values. Attribute values in attributes (of elements, ports, relations, view-only elements and diagram) follow the representations of DISL 4.2, with these rules:

  • An enum value is stored in its stored form: the member's value when the enumeration declares one, and otherwise the member's key, as in DID 0.1 (DISL 4.5). A reader maps a stored form back to its key; an unknown stored form is kept for an extensible enum and reported otherwise.
  • A fixed attribute (DISL 4.3) is a constant of the specification and MUST NOT be written. A reader that finds a stored value for a fixed attribute MUST ignore it, and MUST report a warning when it differs from the fixed value. The stored value is dropped on the next write.
  • A yearMonth value is written "±YYYY-MM": an ISO 8601 year with at least four digits (more when the year needs them) in astronomical numbering, so 0000 is 1 BCE, preceded by - for years before 0000 and by nothing otherwise, then - and a two-digit month. Examples: "2026-09", "0000-01", "-3200-06", "12026-01". A writer MUST write at least four year digits and a leading - for negative years, and MUST NOT write a leading +; a reader SHOULD accept a leading +.
  • A datetime value is written as an RFC 3339 date-time, as in DID 0.1. When the attribute declares writtenPrecision: "preserve", a value MAY also be a full date ("YYYY-MM-DD", RFC 3339 full-date); when it declares timezone: "floating" or writtenPrecision: "preserve", a value MAY also be a local date-time without offset ("YYYY-MM-DDThh:mm[:ss[.fff]]"). A reader MUST accept these forms for such an attribute, and a writer MUST write a value it read, or changed, in the form and precision it was read with (DISL 4.2, writtenPrecision); a new value takes the attribute's newPrecision.

Derived elements. Records of derived types (DISL 4.11) MUST NOT be written: derived elements are computed from the model on every load (section 8.1) and are never part of the stored model. A reader that finds a record of a derived type in elements or relations MUST treat it as unknown content (section 8.2): preserved verbatim on save, left out of the model, and reported.

Relation record (relations[]): id, type, source, target (element or port ids), attributes, x-*. A port id is written "<elementId>#<portId>" when port ids are only unique per element. target MAY be absent when the relation type declares its target end optional (DISL 4.9, target.optional: true), for a relation that has no target yet (a stub); it is written only when the relation has a target. A reader MUST report a relation without target whose type does not declare an optional target end as an unresolvable reference; source is always REQUIRED.

View record (views[]): one per diagram (a definition can hold several diagrams of the same model, one per viewpoint or several of one viewpoint).

Property Type Description
id string View id.
viewpoint string Viewpoint name.
name string Diagram name shown in tabs.
viewport {x, y, zoom} Last viewport, if viewport is in view.store.
nodes map id → NodeView Placement of nodes in this view. Elements not listed are hidden in this view (unless the viewpoint auto-includes them, in which case layout places them).
edges map id → EdgeView Routing and label data.
viewOnly {id, type, attributes}[] View-only elements (notes, frames, images, free text) that belong to this view only.
guides {axis, value}[] User guides.
settings object Per-view settings (grid visible, snapping on/off, theme mode).

NodeView:

Property Description
x, y Position in domain values of the placement's system (numbers, timestamps, band references). Omitted for bound or computed coordinates — bound values live only in the model, never duplicated in the view.
w, h Size in domain units (durations as ISO 8601 on time axes). Omitted when bound, computed or equal to the default (with omitDefaults).
x2, y2 When the placement uses x2/y2 and they are free.
angle, radius Polar placements.
rotation Degrees.
z Integer z-order among siblings.
collapsed bool.
pinned bool (layout respect: "pinned").
params Shape parameter values adjusted by handles (DISL 6.8).
labels map label id → {dx, dy} offsets.
ports map port id → {side, position}.
compartments map id → {collapsed}.
style Style overrides, restricted to DISL's view.styleOverrides.
hidden bool — element placed but hidden.

EdgeView: waypoints (list of Points in domain values), sourceAnchor, targetAnchor ([fx, fy] fixed anchors), controlPoints (for bezier), labels (map id → {at, dx, dy}), routing (per-edge override if allowed), style, z, hidden.

language names the specification: id and version are REQUIRED and equal the specification's language.id and the language.version the definition was written with; definition (the URI of the .dis file) and integrity (its hash) are written when the specification's persistence.definition.embed is "reference" (DISL 11.8). The property keeps the name definition it had in the earlier format.

meta holds the metadata the specification lists in persistence.metadata (DISL 11.8). diagram.attributes holds the attributes of the diagram root element (DISL 4.1).

Suppressions of findings (DISL 8.6) are stored as suppressions: [{constraint, element?, subject?, reason, by, at}]:

Property Description
constraint Required. The id of the constraint or built-in rule whose finding is suppressed.
element The id of the element or relation the finding targets.
subject The subject of a finding that names no element (DISL 8.6, a finding's subject), for a finding about something that is not drawn.
reason Why the finding is suppressed.
by, at Who suppressed it, and when (RFC 3339).

A suppression MUST have exactly one of element and subject. A suppression MUST NOT name an ephemeral id (DISL 11.5); it MAY name a derived element whose id is stable. A stored suppression that names an ephemeral id MUST be ignored, reported as a finding, and dropped on the next write, as view data keyed by one is (section 5). Every DID 0.1 suppression, which always has element, is a valid DID 0.2 suppression.

Referenced from