Labs ICT
Pro Login

JSON Parsing

Converting data to Dart objects.

Parsing JSON in Flutter

JSON is the most common data format you'll encounter when working with APIs. Dart makes parsing JSON easy with the built-in dart:convert library.

To parse a JSON string into a Dart object, use jsonDecode:

import 'dart:convert';

void main() {
  const jsonString = '{"name": "Alice", "age": 25, "isStudent": false}';
  final Map<String, dynamic> data = jsonDecode(jsonString);
  
  print(data['name']);  // Alice
  print(data['age']);   // 25
}

But working with raw maps is messy. The real power comes from creating model classes. You define a class with a fromJson factory constructor:

class User {
  final String name;
  final int age;
  final bool isStudent;

  User({
    required this.name,
    required this.age,
    required this.isStudent,
  });

  factory User.fromJson(Map<String, dynamic> json) {
    return User(
      name: json['name'] as String,
      age: json['age'] as int,
      isStudent: json['isStudent'] as bool,
    );
  }
}

Now you can parse JSON with a clean, type-safe API:

final jsonString = '{"name": "Alice", "age": 25, "isStudent": false}';
final Map<String, dynamic> jsonMap = jsonDecode(jsonString);
final user = User.fromJson(jsonMap);

print(user.name);  // Alice
// user.age = 30;  // Error! age is final

To convert an object back to JSON, add a toJson method:

class User {
  final String name;
  final int age;
  final bool isStudent;

  User({
    required this.name,
    required this.age,
    required this.isStudent,
  });

  factory User.fromJson(Map<String, dynamic> json) {
    return User(
      name: json['name'] as String,
      age: json['age'] as int,
      isStudent: json['isStudent'] as bool,
    );
  }

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

// Usage
final user = User(name: 'Bob', age: 30, isStudent: true);
final jsonString = jsonEncode(user.toJson());
print(jsonString);
// {"name":"Bob","age":30,"isStudent":true}

Handling nested JSON works the same way — just chain your fromJson calls:

class Team {
  final String teamName;
  final User captain;

  Team({required this.teamName, required this.captain});

  factory Team.fromJson(Map<String, dynamic> json) {
    return Team(
      teamName: json['teamName'] as String,
      captain: User.fromJson(json['captain'] as Map<String, dynamic>),
    );
  }
}

These patterns keep your code organized and make API data easy to work with throughout your app.

Try it Yourself ->