Generate code from your model.
EOModeller doesn't bake a code generator into the app. Instead it exports a clean, fully-resolved model JSON, and a small script you run locally turns it into whatever your toolchain needs — CQL, DDL, code, IaC. You see and diff exactly what's produced, and the app never runs anyone else's script.
The loop
- Export the model as JSON from EOModeller.
- Run a generation script against it, locally.
- Review the output and apply it (commit it, run it, ship it).
Step 1 — Export the model JSON
Open the model, go to the model export panel, and click
JSON (next to XMI). You get
<ModelName>.model.json — a flat, semantic view of the
model built for scripting.
Prefer the command line or automation? The same export is a stable API endpoint (auth with a personal access token — see the XMI guide for minting one):
GET /api/workspaces/<workspaceId>/models/<modelId>/export/model.json
Authorization: Bearer eo_pat_… Add ?visual=true to also embed per-element geometry and style
— the same format then doubles as an embedded model for images. Code
generators ignore that block.
What's in the JSON
The export is deliberately easy to parse — no XML, no cross-reference chasing, no stereotype lookups. Everything is resolved:
- Elements and relationships as flat, id-keyed arrays; declared attribute/operation order is preserved.
- Stereotypes carry their resolved name and owning profile — so a column marked
«K»shows up as{ "stereotype": "K", "profileId": "cassandra" }, no registry needed. - Tagged values flattened to a plain
{ name: value }map. - profilesApplied at the top, so a script can check whether the profile it targets is present before doing anything.
A class with the Cassandra «table» stereotype and a few
marked columns exports like this:
{
"formatVersion": "1.0",
"profilesApplied": [{ "profileId": "cassandra", "name": "Cassandra" }],
"elements": [{
"name": "UsersByCity",
"stereotypes": [{ "stereotype": "table", "profileId": "cassandra" }],
"attributes": [
{ "name": "city", "type": "text", "stereotypes": [{ "stereotype": "K" }] },
{ "name": "username", "type": "text", "stereotypes": [{ "stereotype": "C↑" }] },
{ "name": "email", "type": "text", "stereotypes": [] }
]
}]
} Step 2 — Get (or write) a script
A script reads the JSON and writes your target artefact. The reference implementation is a Cassandra CQL generator for the Chebotko notation — Python, standard library only, no dependencies. It maps the profile straight onto DDL:
| In the model | Generated CQL |
|---|---|
«table» on a class | CREATE TABLE |
«udt» on a class | CREATE TYPE |
«K» column | partition key (composite = several, in order) |
«C↑» / «C↓» column | clustering column, ASC / DESC |
«S» column | STATIC column |
«IDX» column | CREATE INDEX |
column type | the CQL type verbatim (text, uuid, set<text>, …) |
Step 3 — Run it locally
python3 generate_cql.py UsersByCity.model.json --keyspace shop > schema.cql The JSON above produces:
CREATE TABLE shop.UsersByCity (
city text,
username text,
email text,
PRIMARY KEY ((city), username)
)
WITH CLUSTERING ORDER BY (username ASC); Partition keys come first and clustering order is preserved because the export keeps your column ordering. Warnings (a table with no partition key, an unsupported format version) go to stderr; the CQL goes to stdout.
Step 4 — Review and apply
Read the generated file — that's the point of doing this locally — then apply it however your target expects:
cqlsh -f schema.cql Writing your own
The reference script is a template. To target a different database,
language, or framework, read the same JSON and emit your own artefact —
key off the resolved stereotype names and
taggedValues rather than the raw UML type. Ship a small
manifest alongside it declaring which profile it consumes and which
formatVersion it supports, so it's discoverable and matched
to the right models.
formatVersion
is MAJOR.MINOR: minor bumps only add optional fields
(backward-compatible); a major bump signals a breaking change, so a script
should check the major it supports and refuse anything newer.What's coming
Today the loop is export → run → apply. Next: an Export to GitHub action that pushes the model JSON straight to a repo, and a shared, community-reviewed library of generation scripts so you can pick one rather than write it. The security model stays the same — scripts run in your CI or on your machine, never inside EOModeller.