Skip to content
Devtoolry

JSON to Dart

Convert JSON to Dart classes for Flutter online, with fromJson and toJson methods or json_serializable annotations, null safety and nested models.

Runs in your browser · Nothing uploaded · No sign-up

Something not working, or missing a feature? Send feedback

About the JSON to Dart

The JSON to Dart converter generates Dart classes for Flutter from a JSON sample, with fromJson factories and toJson methods that follow the null-safety rules. Nested objects become their own classes, arrays become List<T>, and keys missing from some items become nullable fields. You can also generate classes for json_serializable.

Conversion happens in your browser, so your files and records stay private.

How to use the JSON to Dart

  1. Paste a JSON sample and set the root class name.
  2. Choose hand-written fromJson / toJson, or json_serializable annotations.
  3. Copy the code into your project. For json_serializable, run dart run build_runner build to create models.g.dart.

Example

Dart models with fromJson and toJson

Input

{
  "id": 7,
  "fullName": "Grace Hopper",
  "email": null,
  "roles": ["admin"],
  "team": { "name": "Compilers", "size": 4 },
  "projects": [
    { "name": "COBOL", "year": 1959 },
    { "name": "A-0", "year": 1952, "archived": true }
  ]
}

Result

class User {
  final int id;
  final String fullName;
  final dynamic email;
  final List<String> roles;
  final Team team;
  final List<Project> projects;

  const User({
    required this.id,
    required this.fullName,
    required this.email,
    required this.roles,
    required this.team,
    required this.projects,
  });

  factory User.fromJson(Map<String, dynamic> json) {
    return User(
      id: (json['id'] as num).toInt(),
      fullName: json['fullName'] as String,
      email: json['email'],
      roles: (json['roles'] as List<dynamic>).map((e) => e as String).toList(),
      team: Team.fromJson(json['team'] as Map<String, dynamic>),
      projects: (json['projects'] as List<dynamic>).map((e) => Project.fromJson(e as Map<String, dynamic>)).toList(),
    );
  }

  Map<String, dynamic> toJson() {
    return {
      'id': id,
      'fullName': fullName,
      'email': email,
      'roles': roles,
      'team': team.toJson(),
      'projects': projects.map((e) => e.toJson()).toList(),
    };
  }
}

class Project {
  final String name;
  final int year;
  final bool? archived;

  const Project({
    required this.name,
    required this.year,
    this.archived,
  });

  factory Project.fromJson(Map<String, dynamic> json) {
    return Project(
      name: json['name'] as String,
      year: (json['year'] as num).toInt(),
      archived: json['archived'] == null ? null : json['archived'] as bool,
    );
  }

  Map<String, dynamic> toJson() {
    return {
      'name': name,
      'year': year,
      if (archived != null) 'archived': archived,
    };
  }
}

class Team {
  final String name;
  final int size;

  const Team({
    required this.name,
    required this.size,
  });

  factory Team.fromJson(Map<String, dynamic> json) {
    return Team(
      name: json['name'] as String,
      size: (json['size'] as num).toInt(),
    );
  }

  Map<String, dynamic> toJson() {
    return {
      'name': name,
      'size': size,
    };
  }
}

archived is missing from one project, so it is nullable and left out of toJson when null. email was only ever null, so it is dynamic.

Common mistakes

  • Forgetting the generated part file. With json_serializable, the part 'models.g.dart' line fails until you run dart run build_runner build. Rename it if you save the file under another name.
  • Casting numbers with as double. A JSON 1 decodes to an int, so (x as double) throws. Cast through num, as the generated code does.
  • Treating nullable as optional. A key that is present with a null value and a key that is missing both give a null field. If you must tell them apart, check the map with containsKey before using the model.

Works well with the JSON to Dart

Frequently asked questions

fromJson / toJson or json_serializable?

Hand-written methods need no packages or build step, and are enough for most API responses. json_serializable generates that code from annotations, which saves effort for large models but needs json_annotation, json_serializable and build_runner.

Why is a field typed dynamic?

Its value was always null in the sample, or it held values of different kinds, so no single type fits. Use a sample in which the field has a real value.

Why do numbers use (x as num).toInt()?

A JSON number such as 1 can arrive as an int or a double, depending on the decoder. Casting through num works for both, while a plain as double fails on a whole number.

Which Dart version does the code need?

Dart 2.12 or later, because the classes use null safety (String?) and required named parameters.