Skip to content

JSON to schema and types

Paste one realistic example of the data behind a document. You get the JSON Schema it implies — the kind the editor reads for autocomplete — and the TypeScript and Python files formfeed types would write from it.

The data never leaves this tab: the schema and the types are worked out in your browser.

Your data

This tool needs JavaScript: the schema is worked out in your browser, not on a server.

Names the generated types: invoice gives InvoiceData.

The JSON you would send as data. One realistic example is enough.

What it becomes

Paste the JSON you send to a render, and the schema and the types appear here.

What a schema is for here

A template is HTML plus the fields of your data, and every part of Formfeed that helps you write one needs to know what those fields are. The editor reads the schema for autocomplete and to mark a variable your data does not have; formfeed types turns it into a declaration file, so the compiler checks the data your own code sends against the fields of the template.

You never have to write one. A template keeps sample data, and the schema is inferred from it — which is exactly what this page does, with the same function the editor calls.

Why every field comes out optional

One example says what a field looks like when it is there. It cannot say whether it is always there: an invoice without a discount line is not an invoice with a broken one. So the types made from an inferred schema make every field optional, the ones formfeed types writes as well as these.

Write the fields you really depend on into a schema.json beside the template, and the CLI uses that instead and pushes it with the template. Then a missing total is a compile error rather than a blank line in a PDF, a request with validate_data is refused before anything is rendered, and publishing a version that would break the callers you already have is refused unless you say allow_breaking.

The schema above is shown with nothing required for that reason. Saving it as schema.json turns it from a guess into a contract, so decide what belongs in required yourself rather than letting one example decide it.

The same thing, in a project

Once the templates are files in your repository, the CLI does this without pasting. It reads each template folder, prefers a schema.json and otherwise infers over every data set the folder has, so a field only some sets carry comes out optional on purpose:

Shell
# in a template project: reads schema.json, else infers over data/*.json
formfeed types --lang ts

# then the SDK checks the data against the template
# renders.create({ template: 'invoice', data: { … } })
Shell
formfeed types --lang python

# then one method per template
# typed(client).invoice({ … })

With --remote it reads the published version from the API instead (the draft of a template never published), its stored schema or one inferred from its data sets, so the types match what the API will actually render.

Questions

Does my data leave the browser?
No. Both the inference and the emitters run on this page; nothing is uploaded and nothing is stored. You can paste real data and close the tab.
Is this the same output as the CLI?
Yes, byte for byte, for a template of the same name whose only data set is what you pasted: the page calls inferSchema from the engine and generateTypes from the development kit, the same functions formfeed types calls. They live in those packages precisely so a second copy cannot drift from them.
Can I use it without Formfeed?
The JSON Schema, yes — it is an ordinary draft 2020-12 schema. The TypeScript file declares a module augmentation for @formfeed/sdk and the Python file builds on the Formfeed client, so those two only make sense with the SDKs.
What about dates, enums and money?
A date is a string to JSON, so it is typed as one; format the value in the template with date, not in your code. Values that look like a fixed set come out as the type they are, not as a union: one example cannot tell a status of three states from a free-text field.

Start rendering today

The free plan includes 100 units a month and free test renders. Change plans when you need more.