How to deserialize JSON responses in Flutter

Flutter Apr 30, 2023

Communication between a Flutter application and an API often involves handling JSON data. However, due to Dart's type safety, deserializing JSON into Dart objects can be challenging. In this post, we will explore how to effectively deserialize JSON responses in Flutter.

1. Deserialization

Deserialization in Flutter refers to the process of converting received JSON data into Dart objects. We will use an example of deserializing JSON data of rocket launches retrieved from the SpaceX API into a Launch object or a list of Launch objects.

To simplify the deserialization process in Flutter, I recommend using the json_serializable package, along with its dependencies json_annotation and build_runner. If you are unfamiliar with these packages or need a more detailed tutorial, please refer to my other post on how to fetch data from an API in Flutter using the SpaceX API.

How to fetch data from an API in Flutter using SpaceX API
Making a connection between an API and your Flutter application can be done with the help of packages. These packages will make sure that we can send HTTP requests to an API and deserialize the JSON data. During this tutorial, we will be fetching rocket launch data from the SpaceX

For this example, we will create two Dart files:

  1. The launch.dart file, which contains a Launch model.
  2. The launch_client.dart file, which contains a LaunchClient.

Launch

The Launch.dart file represents a Dart model for a Launch object. It defines the structure and properties of a Launch, including the flight number, name, and success status.

import 'package:json_annotation/json_annotation.dart';

part 'launch.g.dart';

@JsonSerializable()
class Launch {
  const Launch({
    required this.flightNumber,
    required this.name,
    this.success,
  });

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

  final int flightNumber;
  final String name;
  final bool? success;
}

In this code snippet, we define the Launch class using Dart annotations. The @JsonSerializable annotation indicates that the class can be serialized and deserialized from JSON using code generation. The class has required properties such as flightNumber and name, and an optional property success. The fromJson factory method is responsible for deserializing a JSON object into a Launch instance.

LaunchClient

The LaunchClient class is responsible for making HTTP requests to the SpaceX API and deserializing the JSON responses into Launch objects.

import 'dart:convert';

import 'package:flutter_deserialize_json_response/models/launch.dart';
import 'package:http/http.dart' as http;

class LaunchClient {
  LaunchClient({http.Client? httpClient})
      : _httpClient = httpClient ?? http.Client();

  final http.Client _httpClient;

  Future<Launch> getLaunch() async {
    final request = Uri.https('api.spacexdata.com', 'v5/launches/latest');
    final response = await _httpClient.get(request);
    final bodyJson = jsonDecode(response.body) as Map<String, dynamic>;

    return Launch.fromJson(bodyJson);
  }

  Future<List<Launch>> getLaunches() async {
    final request = Uri.https('api.spacexdata.com', 'v5/launches');
    final response = await _httpClient.get(request);
    final bodyJson = jsonDecode(response.body) as List;

    return bodyJson
        .map((json) => Launch.fromJson(json as Map<String, dynamic>))
        .toList();
  }
}

In this code snippet, we have the LaunchClient class that handles the API communication. It uses the http package to send HTTP requests. The getLaunch method retrieves the latest launch data from the SpaceX API by making a GET request to the appropriate endpoint. It then deserializes the JSON response into a Launch object using the fromJson method.

Similarly, the getLaunches method retrieves a list of launch data by making a GET request to a different endpoint. It deserializes the JSON array response into a list of Launch objects by iterating over the JSON objects and calling the fromJson method for each.

1.1 Deserialize JSON object

In the LaunchClient on line 15, we decode the JSON using the jsonDecode function and cast it to a Map<String, dynamic>. This is necessary for the fromJson function of the Launch model to correctly deserialize the JSON into a Dart object.

1.2 Deserialize JSON list of objects

Starting from line 23, we decode the JSON using jsonDecode and cast it to a List because we want to iterate over it. On line 26, we go through the list and call the fromJson function on each JSON object.

Similar to before, we ensure that the fromJson function receives the correct data type by casting it to a Map<String, dynamic>. Finally, we use the .toList() function to ensure that we return a list.

2. Conclusion

Deserializing JSON data in Flutter becomes much simpler with the assistance of the json_serializable package. By understanding how to cast JSON data into the appropriate types, you can effortlessly create Dart objects or lists of Dart objects from the JSON responses.

Tags