How to Parse JSON in Dart/Flutter | Shalini Chauhan

Post

How to Parse JSON in Dart/Flutter

Parsing JSON is a very common task for apps that need to fetch data from the Internet.

And depending on how much JSON data you need to process, you have two options:

write all the JSON parsing code manually

automate the process with code generation

Encoding and Decoding JSON

When a JSON response is sent over the network, the entire payload is encoded as a string.

But inside our Flutter apps, we don't want to extract the data from a string manually:

Instead, we can decode the JSON first to obtain a map of key-value pairs that can be more easily parsed. To send JSON data over the network, it first needs to be encoded or serialized. Encoding is the process of turning a data structure into a string. The opposite process is called decoding or deserialization. When you receive a JSON payload as a string, you need to decode or deserialize it before you can use it.

Decoding JSON with dart:convert

For simplicity, let's consider this small JSON payload:

// this represents some response data we get from the network, for example:// ```// final response = await http.get(uri);// final jsonData = response.body// ```final jsonData = '{ "name": "Pizza da Mario", "cuisine": "Italian" }';

To read the keys and values inside it, we first need to decode it using the dart:convert package:

// 1. import dart:convertimport 'dart:convert';// this represents some response data we get from the networkfinal jsonData = '{ "name": "Pizza da Mario", "cuisine": "Italian" }';// 2. decode the jsonfinal parsedJson = jsonDecode(jsonData);// 3. print the type and valueprint('${parsedJson.runtimeType} : $parsedJson');

the result type is the same as Map<String, dynamic>.

Note how the values are of type dynamic. This makes sense because each JSON value could be a primitive type (boolean/number/string), or a collection (list or map).

In fact, jsonDecode is a generic method that works on any valid JSON payload, regardless of what's inside it. All it does is decode it and return a dynamic value.

But if we work with dynamic values in Dart, we lose all the benefits of strong type-safety. A much better approach is to define some custom model classes that represent our response data.

Parsing JSON to a Dart model class

Given this simple map representing a JSON payload:

{

"name": "Pizza da Mario",

"cuisine": "Italian"

}

We can write a Restaurant class to represent it:

class Restaurant {

Restaurant({required this.name, required this.cuisine});

final String name;

final String cuisine;

}

As a result, rather than reading the data like this:

parsedJson['name']; // dynamic

parsedJson['cuisine']; // dynamic

We can read it like this:

restaurant.name; // guaranteed to be a non-nullable, immutable String

restaurant.cuisine; // guaranteed to be a non-nullable, immutable String

This way, we can leverage the type system to get compile-time safety and avoid typos and other mistakes.

However, we haven't specified how to convert our parsedJson to a Restaurant object yet!

JSON to Dart: Adding a factory constructor

Let's define a factory constructor to take care of this:

factory Restaurant.fromJson(Map<String, dynamic> data) { // ! there's a problem with this code (see below) final name = data['name']; final cuisine = data['cuisine']; return Restaurant(name: name, cuisine: cuisine);}

A factory constructor is a good choice for JSON parsing as it lets us do some work (create variables, perform some validation) before returning the result. This is not possible with regular (generative) constructors.


Tagged users
editor-img
Sailesh Verma
@chocolate-89
Developer @Gluelabs
editor-img
Aryan Agarwal
@aryankush25
Technical Lead | Driving Innovation at Glue Labs | Ex - Software Development Engineer at GeekyAnts Just Learning New Things!! 😉