Skip to main content

JSON Schema Output Format

ModelGraphGenerator generates JSON Schema Draft 2020-12 compatible output. This page describes the structure of the emitted schemas.

Top-Level Structure

The output is always a JSON array of schema wrapper objects, even when only one model is discovered:

[
{
"schemaId": "product",
"schemaDefinition": { "$schema": "...", "type": "object", ... },
"metaData": { "description": "..." }
},
{
"schemaId": "order",
"schemaDefinition": { "$schema": "...", "type": "object", ... },
"metaData": { "description": "..." }
}
]

Schema Wrapper Object

Each entry in the array has three fields:

FieldSourceDescription
schemaId@ChimeraSchema(key:)Unique schema identifier
schemaDefinitionGeneratedThe full JSON Schema object
metaData@ChimeraMetaDataMetadata object with description

Schema Definition Structure

The schemaDefinition for a regular model follows this structure:

{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": { ... },
"required": [ ... ],
"additionalProperties": false
}

Fields

FieldSourceDescription
$schemaFixedAlways "https://json-schema.org/draft/2020-12/schema" (root schemas only)
typeInferred"object" for models, "string" for enums
properties@ChimeraProperty annotationsMap of property name → property schema
requiredNon-optional propertiesArray of property names that are required
additionalPropertiesFixedAlways false — no extra properties allowed
info

The $schema field is only emitted on root-level schemas. Nested/child schemas omit it, which is correct per the JSON Schema 2020-12 specification.


Property Schema

Each entry in properties is a property schema object. The @ChimeraProperty annotation supports these overlays:

ParameterJSON Schema KeywordApplies to
descriptiondescriptionAll types
isDeprecateddeprecatedAll types
regexpattern / allOf[].patternStrings
minminimumNumeric types
maxmaximumNumeric types

String Properties

@ChimeraProperty(description: "Username", regex: "^[a-z0-9_]+$")
let username: String
"username": {
"type": "string",
"description": "Username",
"pattern": "^[a-z0-9_]+$"
}

When multiple regex patterns are specified, they are combined with allOf:

"code": {
"type": "string",
"allOf": [
{ "pattern": "^[A-Z]" },
{ "pattern": "[0-9]$" }
]
}

Numeric Properties

@ChimeraProperty(description: "Price", min: 0.0, max: 99999.99)
let price: Double

@ChimeraProperty(description: "Count", min: 0, max: 1000)
let count: Int
"price": {
"type": "number",
"description": "Price",
"minimum": 0.0,
"maximum": 99999.99
},
"count": {
"type": "integer",
"description": "Count",
"minimum": 0,
"maximum": 1000
}

Boolean Properties

@ChimeraProperty(description: "Active status")
let isActive: Bool
"isActive": {
"type": "boolean",
"description": "Active status"
}

Date Properties

Swift Date maps to string with format: "date-time":

@ChimeraProperty(description: "Timestamp")
let createdAt: Date
"createdAt": {
"type": "string",
"format": "date-time",
"description": "Timestamp"
}

URL Properties

Swift URL maps to string with format: "uri":

@ChimeraProperty(description: "Profile picture URL")
let avatarUrl: URL
"avatarUrl": {
"type": "string",
"format": "uri",
"description": "Profile picture URL"
}

UUID Properties

Swift UUID maps to string with format: "uuid":

let requestId: UUID
"requestId": {
"type": "string",
"format": "uuid"
}

Array Properties

let tags: [String]
"tags": {
"type": "array",
"items": { "type": "string" }
}

Set Properties

Swift Set maps to an array with uniqueItems: true:

"categories": {
"type": "array",
"items": { "type": "string" },
"uniqueItems": true
}

Dictionary Properties

Swift Dictionary maps to an object with additionalProperties:

"metadata": {
"type": "object",
"additionalProperties": { "type": "string" }
}

For [Bool: T] dictionaries, a propertyNames constraint is added:

"flags": {
"type": "object",
"additionalProperties": { "type": "integer" },
"propertyNames": { "pattern": "^(true|false)$" }
}

Nested Object Properties

When a property type is itself a model, its schema is inlined (not referenced with $ref):

@ChimeraProperty(description: "Shipping address")
let address: Address
"address": {
"type": "object",
"title": "address",
"properties": { ... },
"required": [ ... ],
"additionalProperties": false,
"description": "Shipping address"
}

Deprecated Properties

@ChimeraProperty(description: "Use newField instead", isDeprecated: true)
let oldField: String
"oldField": {
"type": "string",
"description": "Use newField instead",
"deprecated": true
}

Optional Properties

Optional properties (T?) are excluded from the required array:

@ChimeraProperty(description: "Middle name")
let middleName: String? // → present in properties, absent from required[]

Enum Types

Swift enums with string raw values are emitted as string with an enum constraint:

enum Status: String {
case active, inactive, pending
}
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "string",
"enum": ["active", "inactive", "pending"]
}

Polymorphic (oneOf) Schemas

Type-Level — @ChimeraPolymorphic

A type annotated with @ChimeraPolymorphic generates a oneOf schema with discriminator-based variants:

{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"additionalProperties": false,
"oneOf": [
{
"type": "object",
"title": "car",
"properties": {
"type": { "const": "car" },
"doors": { "type": "integer" }
},
"required": ["type", "doors"],
"additionalProperties": false
},
{
"type": "object",
"title": "truck",
"properties": {
"type": { "const": "truck" },
"payload": { "type": "number" }
},
"required": ["type", "payload"],
"additionalProperties": false
}
]
}

Each variant includes the discriminator field with a const value, and all variant properties are inlined.

Property-Level — @PolymorphicMapping

A property using @PolymorphicMapping generates a nested oneOf:

"vehicle": {
"type": "object",
"additionalProperties": false,
"oneOf": [
{
"type": "object",
"title": "Car",
"properties": {
"type": { "const": "car" },
"doors": { "type": "integer" }
},
"required": ["type", "doors"],
"additionalProperties": false
},
{
"type": "object",
"title": "Truck",
"properties": {
"type": { "const": "truck" },
"payload": { "type": "number" }
},
"required": ["type", "payload"],
"additionalProperties": false
}
]
}

Complete Output Example

[
{
"schemaId": "product",
"schemaDefinition": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Product name"
},
"price": {
"type": "number",
"description": "Price in USD",
"minimum": 0.0
},
"inStock": {
"type": "boolean"
}
},
"required": ["name", "price", "inStock"],
"additionalProperties": false
},
"metaData": {
"description": "A product in the catalog"
}
}
]

Using the Output with OpenAPI

JSON Schema Draft 2020-12 schemas are compatible with OpenAPI 3.1. Extract individual schema definitions with jq:

# Extract the Product schema definition for use in OpenAPI
model-graph-generator --source-path ./Sources --json-schema \
| jq '.[] | select(.schemaId == "product") | .schemaDefinition' > product-schema.json

Then reference in your openapi.yaml:

components:
schemas:
Product:
$ref: './product-schema.json'