ZetCode

Dart JSON

last modified October 18, 2026

In this article we show how to work with JSON in Dart language. We use the dart:convert library.

JSON

JSON (JavaScript Object Notation) is a lightweight data-interchange format. It is easily read and written by humans and parsed and generated by machines. The application/json is the official Internet media type for JSON. The JSON filename extension is .json.

Dart also has JSON code generation packages such as json_serializable and built_value. In this article we focus on the built-in dart:convert library.

For each class that is going to be converted to/from JSON, we define two members: a fromJson constructor and a toJson method.

The fromJson is used for constructing a new object instance from a map structure. The toJson method converts a class instance into a map. These are used in conjunction with the dart:convert functions jsonDecode and jsonEncode.

The jsonDecode function parses a JSON string and returns the resulting Dart object: a Map<String, dynamic>, a List<dynamic>, a String, a number, a bool, or null. The jsonEncode function converts an object to a JSON string. If the object is not one of the built-in types, jsonEncode calls its toJson method.

The json constant is a JsonCodec instance; json.decode and json.encode do the same as the shorthand functions.

Dart JSON simple example

The following is a simple Dart example that works with JSON data.

main.dart
import 'dart:convert';

class User {
  final String name;
  final String occupation;

  User(this.name, this.occupation);

  User.fromJson(Map<String, dynamic> m)
      : name = m['name'] as String,
        occupation = m['occupation'] as String;

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

  @override
  String toString() => '$name|$occupation';
}

void main() {
  const u1Json = '{"name": "John Doe", "occupation": "gardener"}';
  final u1 = User.fromJson(jsonDecode(u1Json));
  print(u1);

  final u2 = User('Roger Roe', 'gardener');
  final u2Json = jsonEncode(u2);
  print(u2Json);
}

In the program, we convert a JSON string to a Dart object and vice versa.

import 'dart:convert';

We import the dart:convert library.

User.fromJson(Map<String, dynamic> m)
    : name = m['name'] as String,
      occupation = m['occupation'] as String;

This creates a new User instance from the map structure. The values in the map are dynamic, so we cast them to the expected type.

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

The toJson method creates a map structure from an object instance.

const u1Json = '{"name": "John Doe", "occupation": "gardener"}';

We define a JSON string.

final u1 = User.fromJson(jsonDecode(u1Json));

We use jsonDecode to convert the string to a map and pass it to the User.fromJson constructor to create a User object.

final u2 = User('Roger Roe', 'gardener');
final u2Json = jsonEncode(u2);

Now we have the reverse operation. We define a User object and transform it into a JSON string using jsonEncode. The function finds the toJson method of the class.

$ dart main.dart
John Doe|gardener
{"name":"Roger Roe","occupation":"gardener"}

Dart list of JSON objects

In the next example, we convert a list of maps into a JSON string.

main.dart
import 'dart:convert';

void main() {
  final users = [
    {'name': 'John Doe', 'occupation': 'gardener'},
    {'name': 'Roger Roe', 'occupation': 'driver'},
    {'name': 'Thomas Brown', 'occupation': 'teacher'}
  ];

  final res = jsonEncode(users);
  print(res);
}

We have a list of users. Each user is defined by a Map<String, String>. We convert the list into a JSON string with jsonEncode.

$ dart main.dart
[{"name":"John Doe","occupation":"gardener"},{"name":"Roger Roe","occupation":"driver"},{"name":"Thomas Brown","occupation":"teacher"}]

Dart pretty-printed JSON

The jsonEncode function produces a compact string. For human-readable output, we create a JsonEncoder.withIndent.

main.dart
import 'dart:convert';

void main() {
  final data = {
    'name': 'John Doe',
    'languages': ['Dart', 'Go'],
    'address': {'city': 'Bratislava', 'country': 'Slovakia'},
  };

  const encoder = JsonEncoder.withIndent('  ');
  print(encoder.convert(data));
}

The argument of withIndent is the string used for one level of indentation.

$ dart main.dart
{
  "name": "John Doe",
  "languages": [
    "Dart",
    "Go"
  ],
  "address": {
    "city": "Bratislava",
    "country": "Slovakia"
  }
}

Dart list of objects

In the next example, we work with a list of User objects.

main.dart
import 'dart:convert';

class User {
  final String name;
  final String occupation;

  User(this.name, this.occupation);

  User.fromJson(Map<String, dynamic> m)
      : name = m['name'] as String,
        occupation = m['occupation'] as String;

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

  @override
  String toString() => '$name|$occupation';
}

void main() {
  final users = <User>[
    User('John Doe', 'gardener'),
    User('Roger Roe', 'driver'),
    User('Finn Bradley', 'teacher')
  ];

  final res = jsonEncode(users);
  print(res);
  print('-' * 34);

  final data = jsonDecode(res) as List<dynamic>;
  final users2 = [
    for (final e in data) User.fromJson(e as Map<String, dynamic>)
  ];

  print(users2);
}

We convert a list of users into a JSON string and vice versa.

final users = <User>[
  User('John Doe', 'gardener'),
  User('Roger Roe', 'driver'),
  User('Finn Bradley', 'teacher')
];

We define a list of user objects.

final res = jsonEncode(users);

The list is encoded into a JSON string with jsonEncode. For each element, toJson is called.

final data = jsonDecode(res) as List<dynamic>;

We decode the JSON string into a list.

final users2 = [
  for (final e in data) User.fromJson(e as Map<String, dynamic>)
];

The list is transformed into a list of User instances with a collection for.

$ dart main.dart
[{"name":"John Doe","occupation":"gardener"},{"name":"Roger Roe","occupation":"driver"},{"name":"Finn Bradley","occupation":"teacher"}]
----------------------------------
[John Doe|gardener, Roger Roe|driver, Finn Bradley|teacher]

Dart nested JSON

JSON documents often contain nested objects and arrays. The fromJson constructor of the outer class delegates to the constructors of the inner classes.

main.dart
import 'dart:convert';

class Address {
  final String city;
  final String country;

  Address.fromJson(Map<String, dynamic> m)
      : city = m['city'] as String,
        country = m['country'] as String;

  Map<String, dynamic> toJson() => {'city': city, 'country': country};
}

class Person {
  final String name;
  final List<String> languages;
  final Address address;

  Person.fromJson(Map<String, dynamic> m)
      : name = m['name'] as String,
        languages = List<String>.from(m['languages'] as List),
        address = Address.fromJson(m['address'] as Map<String, dynamic>);

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

void main() {
  const source = '''
{
  "name": "John Doe",
  "languages": ["Dart", "Go"],
  "address": {"city": "Bratislava", "country": "Slovakia"}
}
''';

  final p = Person.fromJson(jsonDecode(source));

  print(p.name);
  print(p.languages.join(', '));
  print(p.address.city);
  print(jsonEncode(p));
}

The Person class contains a list of strings and a nested Address object. In toJson we return the address object itself; jsonEncode calls its toJson method.

$ dart main.dart
John Doe
Dart, Go
Bratislava
{"name":"John Doe","languages":["Dart","Go"],"address":{"city":"Bratislava","country":"Slovakia"}}

Dart invalid JSON

The jsonDecode function throws a FormatException when the input is not valid JSON.

main.dart
import 'dart:convert';

void main() {
  const bad = '{"name": "John Doe", "age": }';

  try {
    jsonDecode(bad);
  } on FormatException catch (e) {
    print('Invalid JSON: ${e.message}');
  }
}

We catch the exception and print its message.

$ dart main.dart
Invalid JSON: Unexpected character

Dart JSON file

We can read JSON from a file and write it back with the dart:io library.

main.dart
import 'dart:convert';
import 'dart:io';

void main() async {
  final file = File('users.json');

  final users = [
    {'id': 1, 'name': 'John Doe'},
    {'id': 2, 'name': 'Roger Roe'},
  ];

  await file.writeAsString(jsonEncode(users));

  final content = await file.readAsString();
  final data = jsonDecode(content) as List<dynamic>;

  for (final u in data) {
    print('${u['id']}: ${u['name']}');
  }
}

We write a list of maps to the users.json file, read the file back, and decode its content.

$ dart main.dart
1: John Doe
2: Roger Roe

Dart fetch JSON data from URL

In the next example, we fetch JSON data from a URL resource with the http package. We use the free test service jsonplaceholder.typicode.com.

main.dart
import 'dart:convert';

import 'package:http/http.dart' as http;

class User {
  final int id;
  final String name;
  final String email;

  User(this.id, this.name, this.email);

  User.fromJson(Map<String, dynamic> m)
      : id = m['id'] as int,
        name = m['name'] as String,
        email = m['email'] as String;

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

  @override
  String toString() => '$id|$name|$email';
}

void main() async {
  final resp =
      await http.get(Uri.https('jsonplaceholder.typicode.com', '/users'));

  final data = jsonDecode(resp.body) as List<dynamic>;
  final users = [
    for (final e in data) User.fromJson(e as Map<String, dynamic>)
  ];

  print(users.length);
  print(users.first);
  print(jsonEncode(users.first));
}

In the example, we generate a GET request to a web resource. The resource is in JSON format: a list of ten users with many fields. Our User class picks only three of them; the other fields are ignored.

final data = jsonDecode(resp.body) as List<dynamic>;

We decode the response body into a list. If the resource were a named list, for instance {"users": [...]}, we would pick the users field of the decoded map.

$ dart main.dart
10
1|Leanne Graham|Sincere@april.biz
{"id":1,"name":"Leanne Graham","email":"Sincere@april.biz"}

Source

Dart JSON serialization guide

In this article we have worked with JSON data in Dart. We utilized the dart:convert library.

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all Dart tutorials.