How to generate an openapi components/schemas entry from json
- Step 1Collect one complete sample per resource — Gather a full sample for each model — User, Order, Product — with every field populated. The generator only describes keys present in the sample, and for arrays the FIRST element must carry all fields.
- Step 2Load the sample — Drop the
.jsonfile (free tier up to 2 MB) or paste it. Parsing is strictJSON.parseon one value, so remove any trailing commas or comments and don't use NDJSON. - Step 3Name the component via Schema title — Set Schema title to the component name (default
MySchema), e.g.User. It writes to the roottitleonly — handy for documentation, though OpenAPI keys the component by the map key you choose undercomponents/schemas. - Step 4Set required and additionalProperties — Keep Mark all fields required on to get the full
requiredlist. Allow additional properties off emitsadditionalProperties: false, which OpenAPI supports to reject unknown properties on that model. - Step 5Generate, then strip the $schema line — Click Generate Schema and Copy. Delete the
$schemaline (OpenAPI inline schemas don't use it). The rest is your component body. - Step 6Convert for your OpenAPI version and add the $ref — For 3.0, replace each
"type":"null"withnullable: trueon the base type, and lift nested objects into their own components if you want reuse. Reference from a path withschema: { $ref: '#/components/schemas/User' }.
Generated Draft-07 → OpenAPI 3.0 vs 3.1
OpenAPI 3.1 aligns with JSON Schema; 3.0 needs conversions. These are the edits to make after generating.
| Generated | OpenAPI 3.0 | OpenAPI 3.1 |
|---|---|---|
$schema line | Remove (not used inline) | Remove (not used inline) |
{"type":"null"} (from null sample) | type: string + nullable: true | type: ["string", "null"] (kept) |
{"type":"integer"} | type: integer | type: integer |
required: [...] | Kept as-is | Kept as-is |
| inline nested object | Inline OK, or lift to $ref component | Inline OK, or lift to $ref component |
additionalProperties: false | Supported | Supported |
no format/enum | Add format/enum by hand | Add format/enum by hand |
What you must add by hand for a production spec
The generator emits structural types only. These OpenAPI keywords are never inferred and tighten your documentation.
| Keyword | Why add it | Example |
|---|---|---|
format | Document strings precisely | format: date-time on createdAt |
enum | Constrain to allowed values | enum: [active, paused, closed] on status |
example / examples | Render sample values in docs | example: 42 on id |
description | Explain each property | description: ISO order timestamp |
minimum/maximum, minLength/maxLength | Bound numbers and strings | minimum: 0 on amount |
$ref | Reuse nested models as components | $ref: '#/components/schemas/Address' |
Cookbook
A sample resource through to a pasteable components/schemas block — with the 3.0 nullable conversion, the $ref lift for nested objects, and the YAML hand-off.
User sample to a components/schemas entry
ExampleGenerate, strip $schema, and paste under components/schemas. Required defaults give you the required list.
Sample: { "id": 42, "email": "a@b.com", "verified": true }
Schema title: User · required: ON
Generated (after removing the $schema line):
{
"title": "User",
"type": "object",
"properties": {
"id": { "type": "integer" },
"email": { "type": "string" },
"verified": { "type": "boolean" }
},
"required": ["id", "email", "verified"],
"additionalProperties": false
}
// Paste under components: schemas: User:Convert a null field for OpenAPI 3.0
ExampleA null sample value yields type:null, which OpenAPI 3.0 does not allow. Replace with nullable:true on the base type.
Generated: "deactivatedAt": { "type": "null" }
OpenAPI 3.0 (YAML):
deactivatedAt:
type: string
format: date-time
nullable: true
OpenAPI 3.1 (YAML):
deactivatedAt:
type: [string, "null"]
format: date-timeLift a nested object into its own $ref component
ExampleThe generator inlines nested objects. For reuse, move the nested block into its own component and reference it.
Inline (generated):
address:
type: object
properties: { city: {type: string}, zip: {type: string} }
Refactored:
components:
schemas:
Address:
type: object
properties: { city: {type: string}, zip: {type: string} }
User:
type: object
properties:
address: { $ref: '#/components/schemas/Address' }Reference the component from a path
ExampleOnce User lives under components/schemas, reference it in a response. The validator resolves the $ref.
paths:
/users/{id}:
get:
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/User'Emit the spec as YAML
ExampleOpenAPI specs are usually YAML. Generate the JSON schema here, then convert the block to YAML for openapi.yaml.
1. Generate the component as JSON here, remove the $schema line. 2. Paste into /tool/json-to-yaml to convert to YAML. 3. Drop the YAML under components: schemas: <Name>: (YAML preserves key order and types — id stays an integer).
Errors and edge cases
Real errors and silent failures sourced from each platform's own documentation. Match the wording to the row, fix what the row says to fix.
type:null is invalid in OpenAPI 3.0
3.0 invalidA null sample value infers "type":"null". OpenAPI 3.0 has no null type — Swagger/Redoc validators reject it. Replace with the base type plus nullable: true (3.0) or type: ["string", "null"] (3.1). Check every null in your sample before pasting into the spec.
Nested objects are inlined, not split into $ref components
Inline onlyThe generator expands nested objects inline; it does not create separate components/schemas entries with $ref. For reuse across paths, lift each nested object into its own named component manually and reference it. Inline is valid OpenAPI; it's just not DRY.
$schema line must be removed for inline schemas
RemoveThe output starts with $schema: http://json-schema.org/draft-07/schema#. OpenAPI inline schemas don't use $schema — leave it in and some linters warn. Delete the line; the remaining object is your component body.
format, enum, and bounds are never inferred
Not inferredA timestamp string is "type":"string", not format:"date-time", and a status field is not an enum. Add format, enum, minimum/maximum, minLength/maxLength, description, and example by hand — these are what make the documented spec useful and strict.
Array of objects keeps only the first element's keys
Partial schemaItem schemas merge by top-level type, so an array of objects keeps the FIRST element's shape; later-only keys are dropped from items. Your component then under-documents the array. Generate from a sample whose first array element has every field, or hand-complete items.properties.
additionalProperties only on the root model
Root onlyThe Allow additional properties setting writes additionalProperties on the top-level object only — nested objects get none and will accept unknown keys. Add additionalProperties: false to each nested component manually if your spec needs deep strictness.
Component map key vs title
By designThe Schema title is written to the root title, but OpenAPI references a component by its MAP KEY under components/schemas (User:), not by title. Choose the map key deliberately; the title is documentation. They can match or differ.
NDJSON sample or trailing comma fails to parse
Parse errorStrict JSON.parse rejects NDJSON (Unexpected non-whitespace character after JSON), trailing commas, and comments. Clean the sample with the JSON prettifier first, and generate from a single object, not a line-delimited log.
Frequently asked questions
Is the output valid OpenAPI as-is?
Almost. Remove the $schema line, and for OpenAPI 3.0 convert any "type":"null" to nullable: true. The type/properties/required/items keywords map directly onto the OpenAPI Schema Object. 3.1 accepts the JSON Schema form with only the $schema line removed.
How do I handle nullable fields in 3.0 vs 3.1?
A null sample value becomes "type":"null". For 3.0, replace it with the base type plus nullable: true. For 3.1, use type: ["string", "null"] (3.1 aligns with JSON Schema). Always review every null in your sample.
Does it create separate $ref components for nested objects?
No. Nested objects are inlined under the parent. To reuse them across paths, lift each into its own entry under components/schemas and reference with $ref. Inline schemas are valid OpenAPI; splitting is for DRY reuse.
Why is there no format on my date or email fields?
The generator infers structural types only — strings are "type":"string". Add format: date-time, format: email, format: uuid, etc. by hand. The same goes for enum, pattern, and numeric bounds.
How do I turn the component into YAML?
The output is JSON. Convert the component block to YAML with the JSON to YAML tool, then drop it under components: schemas:. Going the other way, YAML to JSON brings an existing spec block back to JSON.
Should I keep additionalProperties: false?
Keep it on the root model if you want OpenAPI to reject unknown properties. Note it is only written on the root — add it to nested objects manually for deep strictness. OpenAPI (3.0 and 3.1) both support additionalProperties.
What's the difference between the title and the component name?
OpenAPI references a component by its map key under components/schemas (e.g. User:). The Schema title is written to the root title for documentation only. They can match but the $ref uses the map key.
Can I generate one combined spec from many resources?
Generate each resource separately, then assemble the components by hand (or merge the JSON objects with the JSON object merger before converting to YAML). Each resource needs its own complete sample.
How do I make fields optional in the component?
Remove their keys from the generated required array (or generate with the required checkbox off). Properties not listed in required are optional in OpenAPI.
Is my sample payload uploaded?
No. Schema generation is 100% client-side. Internal data models and field names never reach JAD Apps servers.
Why did my sample fail to load?
Parsing is strict JSON.parse. Trailing commas, comments, and NDJSON all throw. Reformat with the JSON prettifier or validate with the JSON validator, and generate from a single JSON value.
What's the size limit on the free tier?
2 MB (2,000,000 bytes) per file, one at a time. Pro raises it to 100 MB and 10 files. A single resource sample is normally a few KB.
Privacy first
Conversion runs locally in your browser. No file is uploaded — only metadata counters are saved for signed-in dashboard stats.