April 12, 2026 · 5 min read
Why JSON Schema for Reports
Every reporting engine needs a way to describe what a report looks like. JasperReports chose JRXML — a verbose XML dialect that is painful to read, impossible to diff meaningfully, and hostile to anything other than its own designer tool. Crystal Reports uses a proprietary binary format. FastReport has its own XML variant that is marginally better but still locked to a desktop editor.
We had a choice to make. Here is why we chose JSON.
Why not XML
XML served enterprise software well in the 2000s, but it introduces real friction for modern workflows:
- Diffs are noisy. Attribute ordering, namespace prefixes, and whitespace rules make XML diffs unreliable.
- Tooling is heavy. Parsing XML in the browser requires either a DOM parser or a streaming SAX parser. Both are overkill for a report definition.
- No type inference. XML schemas (XSD) exist but do not map cleanly to TypeScript types. You end up maintaining two parallel type systems.
Why not a proprietary format
Lock-in is the obvious concern, but there is a subtler problem: proprietary formats make automation impossible. If your report template is a binary blob, you cannot generate it from code, transform it in a pipeline, or let an AI agent modify it.
JSON as LLM-native format
This turned out to be the most consequential benefit. Large language models output JSON natively through function calling and structured outputs. An AI agent that can generate valid JSON can generate valid NextReport templates — no special adapter, no conversion layer, no intermediate representation.
When a developer asks an AI assistant to “create an invoice report with company logo, line items table, and a totals footer,” the model can emit a complete NextReport schema directly.
Zod validation + type inference
We define every schema using Zod. This gives us:
- Runtime validation — malformed templates are caught at parse time with clear error messages.
- TypeScript inference —
z.infer<typeof ReportSchema>produces the exact TypeScript type. No manual interface maintenance. - Composability — schemas compose naturally. A
Bandschema containsElementschemas, which referenceExpressionschemas. It reads like code, not configuration.
Schema as universal interface
The JSON schema is the single interface shared by three very different actors:
- Designers use the visual canvas — it reads and writes the schema.
- Developers code against the TypeScript types inferred from the schema.
- AI agents generate and modify the schema through structured output.
Same format. Same validation. Same rendering pipeline. That is the power of choosing the right contract.