Skip to main content

Model JSON contract

editor.model (and the value you persist, send to a server, or hand to another tool) is a plain JSON object. This page documents that wire format as a stable, versioned contract so integrators — Artemis, BESSER, grading scripts — can store and validate diagrams with confidence.

The schema

Apollon publishes a JSON Schema generated from the source UMLModel type and shipped in the package:

import schema from "@tumaet/apollon/schema" with { type: "json" }

It is also resolvable by URL for use with $ref, editor tooling, or CI validators:

https://unpkg.com/@tumaet/apollon/schema/uml-model-4.schema.json

Validate a model with any JSON Schema validator, e.g. ajv:

import Ajv from "ajv"
import schema from "@tumaet/apollon/schema" with { type: "json" }

const validate = new Ajv({ strict: false }).compile(schema)
if (!validate(model)) console.error(validate.errors)

Shape

A v4 model is:

type UMLModel = {
version: `4.${number}.${number}` // wire-format version, currently "4.2.0"
id: string
title: string
type: UMLDiagramType // "ClassDiagram" | "BPMN" | … (13 values)
nodes: ApollonNode[] // diagram elements
edges: ApollonEdge[] // relationships
assessments: { [elementId: string]: Assessment }
interactive?: {
elements: { [id: string]: boolean }
relationships: { [id: string]: boolean }
}
}

The schema is strict about the envelope — unknown top-level, node, or edge fields are rejected, as are a missing version, an unknown diagram type, or a malformed nodes/edges array.

Element data is an open envelope

Each node and edge carries a data object whose shape depends on its type (a class node's name / attributes / methods, a BPMN task's taskType, an edge's multiplicities, colors, …). The schema intentionally leaves data open (additionalProperties) rather than under-describing it; a full discriminated union of all ~50 node types is planned follow-up work. For the concrete per-type fields today, read lib/types/nodes/NodeProps.ts and lib/edges/EdgeProps.ts in the source.

One cross-cutting data field worth knowing: every node — and every class attribute/method — may carry an optional tags: string[] of host-defined grouping labels. See Element tags & group coloring for their normalization rules and the addressing API.

Versioning policy

version tracks the wire-format major line (4.x)not the npm package version. The current canonical model version is 4.2.0. importDiagram accepts every supported v2, v3, and v4 payload, migrates it in place where necessary, and returns the current v4 representation.

The 4.2 minor adds optional, interior-only waypoints to straight connections. When loading a 4.0 or 4.1 model, Apollon discards data.points only on those straight edge families: older releases used that field for inert full-route geometry, which must not become visible user-authored bends. Orthogonal edge waypoints and all other model data are preserved. Models from 4.2 and later keep their straight-edge waypoints unchanged.

ChangeBumpWhat you do
Breaking shape changeMAJORnew top-level version + importDiagram converter
New optional fieldMINORnothing — additive
No shape changePATCHnothing

The schema describes canonical v4 — the output of importDiagram(). Older v2 / v3 payloads are not covered: normalise them first.

import { importDiagram } from "@tumaet/apollon"

editor.model = importDiagram(maybeV2OrV3Json) // → guaranteed v4

Server code that only needs to normalize model JSON can use the DOM-free entry:

import { importDiagram } from "@tumaet/apollon/model"

export const normalizeDiagram = (data: unknown) => importDiagram(data)

The v2 / v3 detectors and converters live behind @tumaet/apollon/internals and are not part of the stability guarantee — only importDiagram is.

This is the diagram data contract. It is unrelated to the standalone webapp's diagram version history feature, which is about storing snapshots over time.

See also: Export and Headless rendering.