Code Generators
JSON to Dart Converter
Paste a JSON or XML sample — the format is auto-detected — and get typed Dart models with names, nesting and nullability inferred for you.
In short
Convert JSON to Dart online: paste a sample and generate typed Dart models with serialization helpers — powered by quicktype, in your browser.
By NaveenKumar T · Updated
- JSON or XML input, auto-detected
- Nested objects become types
- Nullability inferred
Runs entirely in your browser — nothing you paste or open here is uploaded, logged, or stored.How we handle data →
Example
Example: JSON order payload to Dart
A small order document with a nested object, an array of two items, a decimal total and a null field — enough to show how each Dart type, list and nullable is inferred. The same page accepts the XML form of this order too, so the sample below is an example rather than the only accepted format. The right-hand side is the exact output of this tool.
{
"id": "ord_9F2KX",
"status": "processing",
"paid": true,
"customer": { "name": "Ada Lovelace", "email": "ada@example.com", "phone": null },
"items": [
{ "sku": "KB-75", "qty": 1, "price": 149.99 },
{ "sku": "MS-12", "qty": 2, "price": 39.5 }
],
"total": 228.99
}// To parse this JSON data, do
//
// final root = rootFromJson(jsonString);
import 'dart:convert';
Root rootFromJson(String str) => Root.fromJson(json.decode(str));
String rootToJson(Root data) => json.encode(data.toJson());
class Root {
String id;
String status;
bool paid;
Customer customer;
List<Item> items;
double total;
Root({
required this.id,
required this.status,
required this.paid,
required this.customer,
required this.items,
required this.total,
});
factory Root.fromJson(Map<String, dynamic> json) => Root(
id: json["id"],
status: json["status"],
paid: json["paid"],
customer: Customer.fromJson(json["customer"]),
items: List<Item>.from(json["items"].map((x) => Item.fromJson(x))),
total: json["total"]?.toDouble(),
);
Map<String, dynamic> toJson() => {
"id": id,
"status": status,
"paid": paid,
"customer": customer.toJson(),
"items": List<dynamic>.from(items.map((x) => x.toJson())),
"total": total,
};
}
class Customer {
String name;
String email;
dynamic phone;
Customer({
required this.name,
required this.email,
required this.phone,
});
factory Customer.fromJson(Map<String, dynamic> json) => Customer(
name: json["name"],
email: json["email"],
phone: json["phone"],
);
Map<String, dynamic> toJson() => {
"name": name,
"email": email,
"phone": phone,
};
}
class Item {
String sku;
int qty;
double price;
Item({
required this.sku,
required this.qty,
required this.price,
});
factory Item.fromJson(Map<String, dynamic> json) => Item(
sku: json["sku"],
qty: json["qty"],
price: json["price"]?.toDouble(),
);
Map<String, dynamic> toJson() => {
"sku": sku,
"qty": qty,
"price": price,
};
}
Look for the "phone" field: sampled as null, it is typed as dynamic. "items" became List<Item>, and "total" is double.
Learn more
From JSON sample to Dart types
Hand-writing model classes from a JSON payload is transcription work: read a field, type a property, repeat eighty times, miss one. This page runs quicktype (the same engine behind the best-known generators) against your document, merging array elements to find the common shape and naming nested types from their keys.
A field sampled as 1 is typed int, and Dart's fromJson throws a type error if the live payload sends 1.0. The generated code guards decimal fields with a null-aware toDouble() call, but not integer ones. If a numeric field can arrive either way, declare it num or read it with (json['qty'] as num).toInt().
How JSON values become Dart types
Inference works from the values in your sample. Strings map to String, integers and decimals are told apart (228.99 becomes double, while 1 and 2 stay integral), true/false become the language's boolean, and an object such as "customer" becomes its own named type. The "items" array is typed as List<Item> because every element shares the same keys — quicktype unifies the shapes of all array elements into one Item type.
Nulls are the one place inference needs your help: "phone": null carries no type information, so the field is emitted as dynamic. If the real API sometimes sends a string there, include a sample where the field is populated (paste several documents merged into one array) and the generated type becomes the union of what it saw.
Pasting XML instead: how elements and attributes become Dart types
The XML is parsed into a data model before inference (attributes included, text nodes named "text"), so the root element becomes a nested type: <order> is a field of type Order on the top-level Root rather than the top level itself. Child elements become fields, and repeated elements — the two <item> siblings — are collected into List<Item> under an Items wrapper type that mirrors the <items> container.
Attributes and element text are typed differently, and this matters: element text is type-inferred, so <total>228.99</total> becomes double, while attribute values are kept as they were written — qty="1" and price="149.99" stay String in Dart. Prefer element text for numeric data you want typed, or cast attribute values after decoding. One more trap: a single <item> would not be recognized as a list, so make sure repeated elements appear at least twice in the sample.
Annotations, nulls and nested arrays in the generated Dart
There are no annotations and no build_runner step: quicktype writes the mapping by hand. Every class gets a factory fromJson taking a Map<String, dynamic> and reading literal keys, plus a toJson that writes the same keys back, wrapped by top-level rootFromJson and rootToJson helpers around dart:convert. Constructor parameters are named and marked required unless the field is optional. Decimal fields are read defensively through a null-aware toDouble call, which is what saves you when the live payload sends 229 where the sample had 228.99.
A field whose only sampled value is null is typed dynamic — null-safe in the sense that anything fits, which is not much of a promise. Add a document where it carries a value and it becomes String?, a real nullable, and its constructor parameter loses required. Keys absent from some merged samples get the same optional treatment. Everything else is declared non-nullable, so a payload that omits a key throws a type error inside fromJson rather than quietly leaving a null to surface three screens later.
Nested objects become their own classes named from the key — Customer, Item — and the parent factory calls the child's fromJson directly. Lists of objects are typed List<Item> and built by mapping fromJson over the decoded list, then serialized back through a List<dynamic> map of toJson calls. This is the model layer json_serializable would generate for you, minus the codegen ceremony. An empty array types as List<dynamic>, and a single-element array hides every optional field the element may have.
Help
Frequently asked questions
Everything you need to know about the JSON to Dart.
01How do I generate Dart classes from JSON?
Paste a representative document — JSON or XML, the format is detected automatically — and press Convert. A real API response works best. Nested objects become their own Dart types, arrays become List<Item>, and the result downloads as Root.dart.
02What does the generated Dart code include?
Dart models generate with fromJson/toJson methods and null-safe types — the boilerplate every Flutter API integration needs, produced from one sample paste.
03How do I use the generated Dart code in my project?
Add the file to lib/ — it already imports dart:convert. rootFromJson(jsonString) parses and rootToJson(root) serializes, with a fromJson factory and a toJson method on every class. Null safety follows the sample: a field observed as null is typed dynamic, everything else is non-nullable.
04Is the generated Dart null-safe?
Fields observed as null type as nullable (String?), and everything else non-null, matching modern Dart's null safety. For Flutter apps this is exactly the model layer json_serializable would build, minus the build_runner ceremony.
Keep working