json

FormatValidateConvert

JSON to Dart

JSON
Language
Structured output

Source

JSON

Result· read-only

—Dart

The result appears here.

Start over?

This clears the source, the result and the Path.

Generate

JSON to Dart: generate model classes from JSON.

Your document never leaves the browser.

Dart model classes from a JSON sample — in your browser, never uploaded.

Paste the JSON your Flutter or Dart app receives and get a class for every object in it, each with a fromJson factory and a toJson method. The default output is plain Dart 3 with sound null safety, so it compiles in any project without adding a package.

Dart 3

null-safe classes that need no package

int64

the widest integer an int holds; past it, BigInt

0

bytes leave your machine

Classes with fromJson and toJson

Every object in the sample becomes a class with final fields and a const constructor that takes named parameters. A key the class always receives is a required parameter, and a key missing from some records is an optional one: gift-wrap, present on only one line item, becomes the optional giftWrap, and toJson leaves it out while it is null.

note is a different case. Both line items carry it, once as null and once as text, so it stays required and its type is String?. A key such as order_id is renamed to camelCase for the field, orderId, while fromJson and toJson go on reading and writing the original key.

1

The sample, an order with two line items, pasted as the source

{
  "order_id": 1042,
  "placed_at": "2026-09-25T10:15:00Z",
  "paid": true,
  "customer": { "name": "Ada Lovelace", "email": "ada@example.com" },
  "items": [
    { "sku": "PEN-01", "qty": 2, "price": 3.5, "note": null },
    { "sku": "INK-07", "qty": 1, "price": 12, "note": "Fragile", "gift-wrap": true }
  ]
}
2

The classes written for it, at the default settings

// Generated by myjsoneditor.com as plain Dart classes (Dart 3, null safety, no package).
// fromJson reads the map jsonDecode returns; a field without `required` is a key that may be absent.

class Customer {
  final String name;
  final String email;

  const Customer({
    required this.name,
    required this.email,
  });

  factory Customer.fromJson(Map<String, dynamic> json) => Customer(
    name: json['name'] as String,
    email: json['email'] as String,
  );

  Map<String, dynamic> toJson() => {
    'name': name,
    'email': email,
  };
}

class Item {
  final String sku;
  final int qty;
  final double price;
  final String? note;
  final bool? giftWrap;

  const Item({
    required this.sku,
    required this.qty,
    required this.price,
    required this.note,
    this.giftWrap,
  });

  factory Item.fromJson(Map<String, dynamic> json) => Item(
    sku: json['sku'] as String,
    qty: json['qty'] as int,
    price: (json['price'] as num).toDouble(),
    note: json['note'] as String?,
    giftWrap: json['gift-wrap'] as bool?,
  );

  Map<String, dynamic> toJson() => {
    'sku': sku,
    'qty': qty,
    'price': price,
    'note': note,
    if (giftWrap != null) 'gift-wrap': giftWrap,
  };
}

class Root {
  final int orderId;
  final String placedAt;
  final bool paid;
  final Customer customer;
  final List<Item> items;

  const Root({
    required this.orderId,
    required this.placedAt,
    required this.paid,
    required this.customer,
    required this.items,
  });

  factory Root.fromJson(Map<String, dynamic> json) => Root(
    orderId: json['order_id'] as int,
    placedAt: json['placed_at'] as String,
    paid: json['paid'] as bool,
    customer: Customer.fromJson(json['customer'] as Map<String, dynamic>),
    items: (json['items'] as List<dynamic>).map((e) => Item.fromJson(e as Map<String, dynamic>)).toList(),
  );

  Map<String, dynamic> toJson() => {
    'order_id': orderId,
    'placed_at': placedAt,
    'paid': paid,
    'customer': customer.toJson(),
    'items': items.map((e) => e.toJson()).toList(),
  };
}

The json_serializable toggle

json_serializable is off by default. Turn it on for a project that already generates its JSON code with build_runner: each class gets the @JsonSerializable() annotation, a renamed key gets @JsonKey(name: …), and fromJson and toJson call the functions build_runner writes into the part file.

The part file is named after the download, root.g.dart for a pasted sample, so save the classes as root.dart before you run dart run build_runner build. A class that holds another class asks for explicitToJson, so its toJson writes the nested objects as maps as well.

1

An order id and a flag

{ "order_id": 1042, "paid": true }
2

With json_serializable on

// Generated by myjsoneditor.com for json_serializable (Dart 3, null safety).
// Needs json_annotation, and json_serializable with build_runner as dev dependencies;
// run `dart run build_runner build` to write root.g.dart.

import 'package:json_annotation/json_annotation.dart';

part 'root.g.dart';

@JsonSerializable()
class Root {
  @JsonKey(name: 'order_id')
  final int orderId;
  final bool paid;

  const Root({
    required this.orderId,
    required this.paid,
  });

  factory Root.fromJson(Map<String, dynamic> json) => _$RootFromJson(json);

  Map<String, dynamic> toJson() => _$RootToJson(this);
}

Values Dart cannot type from a sample

A field that holds more than one type, or only ever null, is typed Object?, and a comment beside it lists what was seen. Test the value with is before you use it, or give the field a concrete type once you know the data.

Dart’s int is 64 bits on the Dart VM and in a Flutter app on a phone, but compiled to JavaScript for the web it is a double, exact only up to 2^53. An integer past int64 becomes BigInt, read by a small helper at the end of the file. jsonDecode itself turns such a number into a double, so ask the server to send it as a string when every digit matters.

1

A mixed list and a 20-digit number

{ "code": [1, "A"], "account": 12345678901234567890 }
2

Object? with its note, and BigInt with its reader

// Generated by myjsoneditor.com as plain Dart classes (Dart 3, null safety, no package).
// fromJson reads the map jsonDecode returns; a field without `required` is a key that may be absent.

class Root {
  final List<Object?> code; // elements: one of: int, String
  final BigInt account; // past int64 — jsonDecode reads it as a double; send it as a string to keep every digit

  const Root({
    required this.code,
    required this.account,
  });

  factory Root.fromJson(Map<String, dynamic> json) => Root(
    code: List<Object?>.from(json['code'] as List<dynamic>),
    account: _readBigInt(json['account']),
  );

  Map<String, dynamic> toJson() => {
    'code': code,
    'account': account.toString(),
  };
}

// jsonDecode reads an integer past int64 as a double, so a string keeps every digit.
BigInt _readBigInt(Object? value) =>
    value is String ? BigInt.parse(value) : BigInt.from(value as num);

Your sample stays here

Inference and code generation both run inside this browser tab. The sample is never uploaded, stored on a server or logged, because the page has no server to send it to, and once loaded it carries on working with the connection off.

Read next:

FAQ

Frequently asked questions

Didn’t find your answer?Write to us on the contact page →
How do I convert JSON to a Dart class?

Paste the JSON into the source pane and the classes appear beside it, one for each object. Copy them into a file under lib; at the default settings they need nothing beyond the Dart SDK.

How do I convert JSON to Dart with null safety?

Every class is written for Dart 3's sound null safety already. A key that is null in some objects becomes a nullable type such as String?, a key missing from some objects also loses its required keyword, and every other field is a final, required, non-nullable value.

How do I parse JSON in Dart into these classes?

Import dart:convert, then call Root.fromJson(jsonDecode(body) as Map<String, dynamic>), with your root class in place of Root. A file works the same way once you have read it with File.readAsString. To go the other way, pass root.toJson() to jsonEncode.

Should I use the plain classes or json_serializable?

The plain classes suit a small model or a prototype, because what you see is all the code there is. json_serializable suits a large app that already runs build_runner, since the generated part file is rewritten whenever a class changes.

How do I create the .g.dart file for json_serializable?

Add json_annotation as a dependency and json_serializable with build_runner as dev dependencies, save the output under the file name its part line names, then run dart run build_runner build. The part file holds the _$RootFromJson and _$RootToJson functions the classes call.

Do the classes work in Flutter?

Yes. They are ordinary Dart 3 with sound null safety, which every current Flutter release uses, and they behave the same in a Flutter app, on a server or in a command-line tool.

Is my JSON uploaded when I convert it to Dart?

No. The Dart generator runs in this browser tab, so the sample you paste never reaches a server, and the page keeps working with the network switched off once it has loaded.

How is this different from quicktype?

Both read a sample and write null-safe classes with fromJson and toJson. This page shows the classes as you type, beside the JSON, with no account and nothing sent away, and it can switch the same model to json_serializable with one toggle; quicktype offers more output styles, including freezed.

Why is price a double and qty an int?

qty was written without a decimal point in both line items, so it is read as an int. price was 3.5 in one item, so it is a double, and fromJson reads it through num so that a whole price such as 12 is still accepted.

Keyboard shortcuts

Send feedback

Questions, bug reports and feature requests are all welcome. A bug report is easiest to act on with the shape of the document that caused it — never send anything confidential.

Email us

Contact page, in a new tab, so this page stays as it is.

Settings

Indent

The result is written with it — YAML and XML at 2 spaces when it is Tab.

Code text size
14 px

Both panes.

Wrap long lines

Load from a URL

Your browser fetches it directly — the request goes to that site, never to us.