JSON to Dart and TypeScript
Paste one or more JSON samples, or a JSON Schema, and get Dart classes with fromJson and toJson, or TypeScript interfaces. A key missing from some records becomes optional and a key that is sometimes null becomes nullable, and TypeScript keeps the two apart as name? and | null. Keys that are not legal identifiers keep their exact JSON spelling in the generated mapping, and a report lists every renamed key and every field that was typed loosely, with the reason. Local $defs references are followed; external references are refused, never fetched. Generation runs in a background worker in your browser using the pinned quicktype-core 26.0.0 engine, and the source it writes is shown, never run.
Your JSON
Generated source
Paste JSON samples or a JSON Schema, then generate Dart or TypeScript.
- Language
- Dart
- Root type
- None yet
- Classes
- 0
- Fields
- 0
- Warnings
- 0
Common questions
- How does it decide which fields are optional or nullable?
- From the samples. A key missing from at least one object at the same place becomes optional, a key that is null in some objects becomes nullable, and a key that is null everywhere has an unknown type. A top-level array is read as a list of records, and several documents pasted one after another count as several samples of the same root. TypeScript writes optional as name?: and nullable as | null. Dart types both as nullable, such as String?, and a field present in every sample stays a required constructor argument even when it can be null. The Every field optional policy makes all fields optional instead.
- What happens to keys like first-name or class?
- TypeScript keeps each key exactly, quoted where it is not an identifier, such as "first-name". Dart needs identifiers, so first-name becomes firstName and a reserved word such as class gets a prefix. Keys that would otherwise land on the same name, like first-name, first_name and first name, each get their own name, and fromJson and toJson still read and write each exact JSON key. Names that clash with members every Dart class has, such as hashCode and toString, are renamed too. The key mapping table lists every rename. A key that appears twice in one object is refused with its line and column, because JSON readers keep only one copy.
- Which JSON Schema features are supported?
- Types, properties, required, type arrays that include null, enums, arrays, oneOf and anyOf, and local references written as JSON pointers into $defs or definitions, including recursive ones, up to 500 local definitions. External references to URLs or other files, anchor references such as #name, $dynamicRef and a nested $id are refused with a message that says where they are, and nothing is fetched. Rules such as pattern, minimum and format are listed as not enforced by the types, and string formats stay strings. oneOf and anyOf with more than one non-null type become unions in TypeScript and dynamic in Dart. Objects that allow extra properties get an index signature in TypeScript; Dart classes drop keys they do not declare.
- What do the Dart copyWith and private field options do?
- Add copyWith generates a method that returns a copy with the fields you pass replaced. It keeps the current value when you pass null, so it cannot clear a nullable field. Private fields with getters stores each value in a private final field such as _name, set through the constructor's initializer list, and exposes it through a getter with the public name. fromJson and toJson are the same either way, and fields are final in both styles. The Root type name names the root class, or the record class when the root is an array.
- What does the TypeScript Convert option add?
- By default the TypeScript output is interfaces and type aliases only. Runtime-checked Convert helpers adds a Convert class whose functions parse a JSON string into your types and throw if a value does not match them, plus the reverse. The code is only generated here; this page never runs it.
- Why did an object become a map instead of a class?
- When an object's keys look like data rather than field names, such as numeric IDs, or an object has more than 500 keys, it is read as a map: Map<String, T> in Dart or { [key: string]: T } in TypeScript. The report says when this happened. Turn off Read data-like keys as maps to get a class with one field per key instead.
- Why is a number typed int in Dart?
- A field that held only whole numbers in every sample becomes int, and one that mixed whole and decimal numbers becomes double. If real data can later carry a decimal, parsing it as int fails, so the report lists every int field. Whole numbers beyond 9,007,199,254,740,991 are flagged as well, because a JavaScript number cannot hold them exactly.
- Is my JSON uploaded, and are there limits?
- Nothing is uploaded: the page makes no network request with your input. The JSON you paste or open is never written to storage, because samples often hold real records or tokens. Only your settings (input kind, language, root type name, null policy and options) are remembered in this browser's local storage for next time; Start over clears them. JSON nested deeper than 256 levels is refused, a schema may hold up to 500 local definitions and 5,000 references, and a generation that runs longer than 30 seconds is stopped with your input left in place. Cancel stops it at any time. Beyond that, the practical ceiling is your device's memory.
Sample inference cannot know absent fields or all future types. No execution or automatic API calls.