100% local — your data never leaves your browser

JSON to Dart — fromJson and toJson Written Out

Turn a JSON sample into Dart classes. The original keys live in the generated fromJson and toJson, so the mapping is code you can read and step through.

Instant Private Zero cookies

JSON input

Dart output

What this tool does

A JSON sample becomes Dart classes, each with a fromJson factory and a toJson method.

{ "id": 1, "firstName": "Ada", "address": { "city": "Paris" } }
class Root {
  final int id;
  final String firstName;
  final Address address;

  Root({required this.id, required this.firstName, required this.address});

  factory Root.fromJson(Map<String, dynamic> json) => Root(
        id: json['id'] as int,
        firstName: json['firstName'] as String,
        address: Address.fromJson(json['address'] as Map<String, dynamic>),
      );

  Map<String, dynamic> toJson() => <String, dynamic>{
        'id': id,
        'firstName': firstName,
        'address': address.toJson(),
      };
}

No build_runner, no annotations, no generated part file: the mapping is right there, and you can change it.

The key never leaves

Dart field names cannot hold a dash or start with a digit, and class is reserved. When a name has to change, both directions keep the key:

  final String contentType;
  final int class_;

  factory Root.fromJson(Map<String, dynamic> json) => Root(
        contentType: json['content-type'] as String,
        class_: json['class'] as int,
      );

  Map<String, dynamic> toJson() => <String, dynamic>{
        'content-type': contentType,
        'class': class_,
      };

Because the mapping is code rather than a convention, nothing is guessed at runtime — and you can read what will be sent before you send it.

Lists and nested objects

A list of objects becomes a class of its own, and the mapping walks it:

        items: (json['items'] as List<dynamic>)
            .map((e) => ItemsItem.fromJson(e as Map<String, dynamic>))
            .toList(),

A list of scalars uses cast, which is cheaper: (json['tags'] as List<dynamic>).cast<String>().

What a sample cannot say

Every field is final and required, and none is nullable — because the document had a value for each. That makes a missing key a TypeError at decode time, naming the field, rather than a null that travels three screens before it breaks.

Only a null gives dynamic, which accepts anything and checks nothing. An empty or mixed list gives List<dynamic> for the same reason. Those are the three places worth revisiting once you have a second payload.

Private by design

Everything runs locally in your browser with JavaScript. Your data is never uploaded, which makes the tool safe for sensitive content, and it keeps working offline.

Frequently asked questions

Do I need json_serializable or build_runner?
No. The `fromJson` factory and `toJson` method are written out in full, so the class works with `jsonDecode` and nothing else. If your project already uses json_serializable, its generated code does the same job with annotations instead — this output is the version you can read without running a build.
What happens if a key is missing at runtime?
The cast throws. `json['id'] as int` on a missing key is a `null` cast to `int`, which raises a `TypeError` naming the field. That is the loud failure, and it is the right one: a sample that always had the key cannot tell you it is optional. Make the field `int?` and drop the `required` when you know better.
Can I turn the JSON methods off?
Yes — the toggle leaves the class with its fields and constructor only. That is useful when you are pasting into a codebase that generates serialization elsewhere, or when the class is a plain value holder that never meets JSON.

Related converters