Dataset metadata
Optional descriptive fields. label defaults to "Untitled dataset".
About the JSON-stat Builder
The JSON-stat Builder is a browser-based tool for creating JSON-stat datasets interactively. Instead of hand-writing the JSON-stat format, you describe your data through a guided wizard and the tool serializes a correct, validated dataset for you — ready to copy or download. No command line, no build step.
At a glance: design a cube → paste your data → export a valid JSON-stat 2.0
dataset. Click Load demo for a worked example (population by geography, sex and year) in seconds.
Think in cubes
A spreadsheet is a flat grid. JSON-stat is a cube: every observation sits at the crossing of one category per dimension. So you model first — name your dimensions (e.g. geography, sex, year), give each an ordered list of categories (e.g. Spain, France), and assign roles (time, geo, metric). The order you define dimensions in even governs how values are stored.
A guided, step-by-step workflow
- Metadata — label, source, updated date, optional href and notes.
- Dimensions & categories — define each dimension, its categories, and roles.
- Layout — place each dimension on the row or column axis. Presentation only; it never changes the exported cube.
- Data — fill the grid with your numbers.
- Output — generate, validate, preview, copy, download.
Move back and forth freely — refining an earlier choice is always one click away.
Feed it data your way
Enter values by hand, paste a spreadsheet block, paste CSV/TSV, or paste tidy data (one observation per row). The importer auto-detects tab, comma, semicolon and whitespace separators. An empty cell means a missing value (null); annotate observations with free-form status codes (estimated, provisional, …).
Always valid, by construction
On every Generate, the output is checked with the official JSON-stat tooling — vendored so it works fully offline — running structural and semantic checks, then read back to confirm every cell is reachable. Copy and Download stay disabled until there are zero errors, so you never walk away with a broken file.
Dimensions & categories
Define each dimension in canonical order. This order drives how values are serialized.
Help — dimensions & categories
Here you model the cube: each dimension gets an id, a label, a role, and an ordered list of categories. The order you define dimensions in drives how values are serialized, so put them in their canonical order.
Required vs optional
- Dimension id — required (must be unique).
- At least one category — required (the last category can't be removed).
- Label, role — optional (the label just makes output more readable).
Roles
Pick a role per dimension from the dropdown: classification (the default), time, geo, or metric. Typically a cube has a single metric dimension (the thing being measured). Only metric dimensions expose the optional Unit… editor.
Two ways to enter categories
- By hand — click + category and type an
idandlabelper row. - Import list… — paste rows (or load a
.csv/.tsv/.txtfile) to fill a whole dimension at once.
Import format & column shapes
Paste rows — or load a file — CSV, TSV, semicolon, or whitespace separated, no header row. The widest row decides the shape; the extra columns are optional:
id,label— the usual shape.id,label,parent— hierarchy (the parent is a category id; order doesn't matter).id,label,lon,lat— coordinates (geo dimensions only).id,label,lon,lat,parent— coordinates and hierarchy (geo only).
A single pasted column is read as labels (the label is reused as the id). Importing replaces the current categories (and any coordinates/parents already set) — it's a pure replace, not a merge.
Optional per-dimension extras
- Unit… (metric only) — per-category
decimals,label,symbol,position. Most datasets leave it blank; all-blank fields are omitted on export. - Extension… (any dimension) — a free-form JSON object emitted verbatim as the dimension's
extension. The app never interprets it.
Row / column layout
Assign each dimension to the row or column axis. The serialized cube is the same regardless of layout, but the layout defines the grid below — so choose the layout that matches how your data is arranged, so the pasted values line up correctly.
Help — row / column layout
Every dimension must live on exactly one axis — the row axis or the column axis — and you can order each axis independently. This step is about how the grid looks.
How to use it
- → columns / ← rows — move a dimension between the two axes.
- ↑ / ↓ — reorder a dimension within its axis.
- Dimensions you add in Step 2 default to the row axis.
Required
Each dimension must be assigned to one axis (not both, not neither). Otherwise Step 4 will tell you to assign dimensions to rows and columns first before you can paste data.
Presentation-only — but it matters
The serialized cube is the same regardless of layout. Layout only controls the shape of the Step 4 data grid and its headers. So pick the layout that matches how your pasted values are arranged — that way the numbers line up with the row and column headers and a wide-paste lands correctly.
Enter data
Paste data
or load a file:
Grid
Status — observation metadata (e.g. estimated, provisional). Optional; independent of values, so even missing cells can be annotated.
Paste status grid-shaped (same rows×cols as the data grid; blank = no status). Separate cells with tab, semicolon, or spaces; join several codes in one cell with a comma (e.g. e,p). Codes not in the vocabulary above are skipped.
or load a file:
Help — enter data
Fill the grid with one observation per cell. A blank cell means a missing value (null). Values are optional but expected; you can leave gaps.
Two input formats
Choose a format with the Data format dropdown:
- Grid of values (wide)
- Paste a block with the same shape as the grid (the rows × columns set by your Step 3 layout), or load a
.csv/.tsv/.txtfile into the box. You can also edit individual cells directly in the grid. Separators are auto-detected: tab, comma, semicolon, or whitespace. - One observation per row (tidy)
- A header row naming each dimension, followed by one row per observation, plus a
valuecolumn and an optionalstatuscolumn. Tidy fills by coordinate, so it works with any layout; categories not in your dimensions are skipped.
Reading & clearing
Read → grid parses the paste into the grid; Clear cells empties every value (the dimensions and layout are kept).
Status (optional, collapsible above)
Status is observation metadata (e.g. estimated, provisional) — independent of values, so even missing cells can be annotated.
- + status code builds the vocabulary (each code + label).
- Status for all cells sets a baseline applied everywhere; per-cell edits add/remove on top.
- Edit status per cell turns on per-cell chip editing in the grid.
You can also paste a status grid — or load one from a file — with the same rows × columns as the data grid, blank = no status. Separate cells with tab, semicolon, or spaces, and join several codes in one cell with a comma (e.g. e,p). Codes not in the vocabulary are skipped.
Generate & export
JSON-stat output
Preview
Help — generate & export
Generate the JSON-stat document, validate it, preview it, then copy or download.
Value type
Choose how value is stored: dense (an array) or sparse (an object keyed by linear index). On Generate, the type auto-switches to sparse when nulls outnumber values; you can override by manually selecting dense.
Validation (always on)
Every Generate runs the official JSON-stat tooling — vendored so it works fully offline — performing structural and semantic checks, then reads the document back to confirm every cell is reachable. Copy and Download stay disabled until there are zero errors, so you never walk away with a broken file.
Preview
A crosstab of the generated cube, mirroring your Step 3 layout.
Starting from an existing dataset
The Open… button in the top bar loads an existing JSON-stat 2.0 dataset three ways: paste the JSON text, choose a .json file, or fetch from an API endpoint (GET, or POST with a JSON body). Loading replaces the current dataset.