Tools mentioned in this article
Open the browser-based tool while you read and try the workflow immediately.
The tedium of nested schema definitions
The OpenAPI Specification (OAS) is the standard, language-independent way to describe a RESTful API’s interface (formerly known as “Swagger”). It underpins auto-generated documentation, client SDK generation, and mock servers.
Hand-writing the “Schema” for a request or response body — mapping deeply nested objects to type / properties / required / items — is slow and error-prone.
The JSON to OpenAPI Generator takes a sample JSON payload and produces a components/schemas definition automatically.

How type inference works
The generator walks the JSON value by value, mapping each one to an OpenAPI type.
private static inferSchema(value: unknown): OpenApiSchema {
if (value === null) return { type: 'null' };
if (Array.isArray(value)) {
// if every item shares one schema, use it directly; otherwise wrap in oneOf
const itemSchemas = this.mergeSchemas(value.map((item) => this.inferSchema(item)));
const items = itemSchemas.length === 1 ? itemSchemas[0] : { oneOf: itemSchemas };
return { type: 'array', items };
}
if (typeof value === 'number') {
return { type: Number.isInteger(value) ? 'integer' : 'number' }; // distinguish int from float
}
// objects recurse into properties; every key present is treated as required
}
Two details matter here:
- Numbers are classified with
Number.isInteger—30becomesinteger,30.5becomesnumber. - Mixed types inside an array become
oneOf. An array like["admin", 1, true]producesitems: { oneOf: [{type: string}, {type: integer}, {type: boolean}] }.
Automatic date-string detection
ISO 8601 strings are matched against a regular expression and get format: date-time attached automatically.
if (/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?Z$/.test(stringValue)) {
return { type: 'string', format: 'date-time' };
}
A value like 2026-01-15T12:00:00Z is detected, but date-only strings (2026-01-15) or ones with a timezone offset (+09:00) don’t match this pattern — you’ll need to add format: date manually for those after generation.
Usage and example output
{
"id": 123,
"name": "Yamada Taro",
"email": "taro@example.com",
"roles": ["admin", "editor"],
"profile": {
"createdAt": "2026-01-15T12:00:00Z",
"isActive": true
}
}
From this, id is inferred as integer, name/email as string, roles as array, profile as a nested object, and createdAt as a string with format: date-time.
- Get a real JSON payload from an API call
- Paste it into the JSON to OpenAPI Generator
- Get a
components/schemasdefinition within seconds - Merge the generated definition into your
openapi.yaml
Every key present becomes “required” — by design
Under the current implementation, every key present in the sample JSON is marked required.
for (const [key, val] of Object.entries(value)) {
properties[key] = this.inferSchema(val);
required.push(key); // any key present is unconditionally required
}
This is a deliberate simplification: from a single sample JSON payload alone, there’s no way to tell whether a key is genuinely required or just happened to have a value that time. If your real API has optional fields, remove them from required manually after generating.
What to double-check after generating
Treat a JSON-derived OpenAPI schema as a high-quality draft, not a finished spec.
- Remove fields from
requiredthat can legitimately be omitted - Confirm whether numeric fields (IDs, amounts, counts) should be
integerornumber - Confirm date strings have the
formatyou expect — onlydate-timeis auto-detected - Check that arrays weren’t sampled empty (an empty array becomes
items: {}) - Add
descriptionandexampleso consumers understand what each field means
OpenAPI 3.1 compliance
The generated schema targets OpenAPI 3.1.0. Rather than OpenAPI 3.0’s nullable: true, it uses the type: "null" (or union type) form standardized in 3.1. If your existing project is standardized on OpenAPI 3.0, you may need to translate this difference.
FAQ
Does it work for Swagger too?
Yes. OpenAPI was previously called Swagger, and the terms “Swagger schema” and “Swagger UI” are still common. The generated schema can be used directly with Swagger UI and similar documentation tools.
Can I use it for both request and response bodies?
Yes — POST/PUT request JSON, GET response JSON, webhook payloads, anything with a discoverable JSON structure works as a starting point.
What happens if an array has mixed types?
The generator expresses it with oneOf, listing each distinct type. Decide as part of your API design whether to unify the type or accept the oneOf as-is.
Should I worry about OpenAPI 3.0 vs 3.1?
If your existing project is standardized on OpenAPI 3.0, check how nullable vs. type: null is handled before importing the output. For new projects or internal tooling, sticking with the OpenAPI 3.1 representation is usually fine.
Summary
- Type inference is a recursive value walk: numbers split into integer/float, mixed-type arrays become
oneOf - Date detection is regex-based and only covers
date-timeformat — everything else needs manual adjustment - Every key present in the sample becomes
required— remove optional fields after generating - Output targets OpenAPI 3.1.0
Auto-generation is a draft. Add description and example afterward to turn it into documentation your team and API consumers will actually enjoy reading.