JSON to Dart Class
Generate null-safe Dart classes from a JSON sample, with a const constructor, fromJson and toJson. Every value is typed, and a key that some objects lack or hold as null is nullable.
About JSON to Dart
The objects in the JSON become Dart classes, each with final fields, a const constructor with named parameters, a fromJson factory and a toJson method. They need no package: jsonDecode and jsonEncode from dart:convert are enough.
Every value counts, not just the first. A number is an int unless one is written with a fraction or an exponent, as 10.0 and 1e3 are, since dart:convert reads those as a double. The objects at one place, such as the items of a list, make one class. A key that is null in some objects, or missing from some, is nullable, as in String?, and not required. A key that holds two kinds of value, such as a string and a number, or only null, is dynamic, and a note says why.
Fields are lowerCamelCase, so user_id and userID both read as userId, and the second gets a number: userId2. A name a field cannot take, such as class or toString, has Value added, and a class name that would hide one from dart:core, such as Map, has Model added. Each key is still read and written exactly as it is, __proto__, $ref and it's included.
An integer beyond the 64 bits of a Dart int is read by dart:convert as a double, so its field is a double, with a note, and another note names each field holding an integer that an app compiled to JavaScript would round. When the JSON is an array of objects, the class describes them, and a note gives the line that reads the whole list. Choose Every field to make every field nullable, for an API that can leave any key out. Everything runs in your browser.
For TypeScript types from JSON, see JSON to TypeScript. For Go structs, try JSON to Go Struct. For Rust, see JSON to Rust Struct.
Built and maintained by Meet Shah · Last updated
What this tool is used for
- Generating a model class from an API response for a Flutter app.
- Producing fromJson and toJson methods rather than writing them by hand.
- Getting a starting model for an endpoint with no schema.
- Creating classes for a fixture that match production shapes.
- Seeing how a payload's nesting maps onto nested Dart classes.
Frequently Asked Questions
- How do JSON types map to Dart?
- Strings are
String, booleansbool, objects a class and arrays aList. A number is anintunless a sample has a fraction or an exponent, as 10.0 and 1e3 do: dart:convert reads those as adouble. A key null in some samples is nullable, as inString?; one always null, or with two kinds of value, isdynamic. - Why does an int sometimes need to be double?
- A field can hold 0 in one response and 0.5 in the next. dart:convert gives an
intfor 0 and adoublefor 0.5, and on the Dart VMas doublethrows on the 0 andas inton the 0.5. So a field with a fraction in any sample is adouble, and each number is read throughnum, as in(json['x'] as num).toDouble(). - What generates fromJson and toJson?
- They are emitted as plain methods, so the class works with
dart:convertand no build step.json_serializablegenerates equivalent code from annotations, which is worth adopting once the number of models grows. - How is an array of objects handled?
- Its objects are merged into one class, so a key that only some of them have still becomes a field, nullable and not required, and a number that is 12 in one and 12.5 in another makes a
double. When the whole JSON is an array, the class describes its objects, and a note gives the line that reads the list. - Should the fields be nullable?
- Under sound null safety, a field an API can leave out or send as null needs a
?, or its cast in fromJson throws on that response. A sample shows only some of those: here a key that is null, or missing from some of its objects, is nullable. The API contract says which others are; Every field makes them all nullable. - Is a value class better than a plain class?
- For models compared or used as map keys, yes — Dart's default equality is by reference, so two identical parses are not equal.
freezedor a manual==andhashCodefixes that; the generated class is the starting point.
Common errors and gotchas
- Trusting the nullability one sample shows: a key present in every object of the sample can still be left out of a real response, and a field that is not nullable then throws in fromJson. Choose Every field when the API contract does not say.
- Generating from a sample where a decimal field happens to hold a whole number, such as a price of 12: the field is typed
int, and(json['price'] as num).toInt()then turns 12.5 into 12. Use a sample with a fraction, or write 12.0. - Assuming generated code handles a missing key, where a non-nullable field will throw on decode.
- Keeping a class name made from a key without reading it: a list's class takes the singular of its key, so
ordersgivesOrderandpeoplegivesPerson, but a key such asdatagives a class namedData, which says little. Rename it in the code, and give the root class its name in Class name. - Sending an ID above 2^53 as a JSON number: a native Dart or Flutter app reads it exactly, since a Dart int holds 64 bits, but an app compiled to JavaScript can round it, and one beyond 64 bits is read as a double everywhere. Send such an ID as a string.