In this article you’ll learn how to serialize JSON data into model classes. A model class represents data for a particular object. For example a User model class will usually have user names, age, date of birth and more.
What is JSON
JSON, which stands for JavaScript Object Notation, is an open-standard format used on the web and in mobile clients. It’s the most widely used format for Representational State Transfer (REST)-based APIs that servers provide read more. If you talk to a server that has a REST API, it will most likely return data in a JSON format. An example of a JSON response looks something like this:
{
"names": "prosper absalom",
"gender": "male",
}
While it’s possible to treat the JSON as just a long string and try to parse out the data, it’s much easier to use a package that already knows how to do that. Flutter has a built-in package for decoding JSON, but in this article, you’ll use the json_serializable and json_annotation packages to help make the process easier.
Flutter’s built-in dart:convert package contains methods like json.decode and json.encode, which converts a JSON string to a Map and back. While this is a step ahead of manually parsing JSON, you’d still have to write extra code that takes that map and puts the values into a new class.
The json_serializable package comes in handy because it can generate model classes for you according to the annotations you provide via json_annotation. Before taking a look at automated serialization, you’ll see in the next section what manual serialization entails.
Writing the code yourself
So how do you go about writing code to serialize JSON yourself? Typical model classes have toJson() and fromJson() methods.
First, you’d create a model class:
class User {
final String name;
final String age;
User({this.name, this.age});
}
Then you’d add a toJson() factory method and a fromJson() method:
factory User.fromJson(Map<String, dynamic> json) {
return User(json['name'] as String, json['age'] as String);
}
Map<String, dynamic> toJson() {
return <String, dynamic>{ 'name': name, 'age': age}
}
In fromJson(), you grab data from the JSON map variable named json and convert it to arguments you pass to the User constructor. In toJson(), you construct a map using the JSON field names.
While it doesn’t take much effort to do that by hand for two fields, what if you had multiple model classes, each with, say, five fields, or more? What if you renamed one of the fields? Would you remember to rename all of the occurrences of that field?
The more model classes you have, the more complicated it becomes to maintain the code behind them. Fear not, that’s where automated code generation comes to the rescue.
*Automating JSON serialization
*
We will use two packages: json_annotation and json_serializable from Google.
You use the first to add annotations to model classes so that json_serializable can generate helper classes to convert JSON from a string to a model and back.
To do that, you mark a class with the @JsonSerializable() annotation so the builder package can generate code for you. Each field in the class should either have the same name as the field in the JSON string or use the @JsonKey() annotation to give it a different name.
Adding the necessary dependencies
Open your project and in pubspec.yaml in the dependencies
section add the following
json_annotation: ^4.8.0
In the dev_dependencies section and the following dependencies
build_runner: ^2.3.3
json_serializable: ^6.6.1
build_runner is a package that all code generators require in order to build .part file classes.
Finally, press the Pub get button you should see at the top of the file. You’re now ready to generate model classes.
Generating classes from JSON
Start by creating a new file named user_model.dart in the lib folder. Then add the needed imports:
import 'package:json_annotation/json_annotation.dart';
//
part 'user.g.dart';
The json_annotation library lets you mark classes as serializable. The file user.g.dart
doesn’t exist yet; you’ll generate it in a later step.
Then add the following code
@JsonSerializable()
class User {
final String name;
final int age;
// constractor
User({
required this.name,
required this.age,
});
}
@JsonSerializable() annotation marks the User class as serializable so the json_serializable package can generate the .g.dart file
Converting to and from JSON
// User.fromJson method
factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
//
Map<String, dynamic> toJson() => _$UserToJson(this);
Note that the methods on the right of the arrow operator don’t exist yet, so ignore any red squiggles. You’ll create them later by running the build_runner command.
Note also that the first call is a factory method. That’s because you need a class- level method when you’re creating the instance, while you use the other method on an object that already exists.
Generating the .part file
Open your terminal and in your project root run the following
flutter pub run build_runner build
This command creates user.g.dart in the network folder. If you don’t see the file, right-click on the network folder and choose Reload from disk.
And that's it, Now you can parse model objects from JSON, and to JSON.
This article walks through the steps of adding the necessary dependencies, marking classes with the @JsonSerializable() annotation, and generating the .g.dart file using the build_runner command. It also provides an example of creating a User model class with a constructor, a factory method to convert JSON to a model, and a toJson() method to convert the model back to JSON.
In summary, using the json_serializable and json_annotation packages can significantly simplify the process of converting JSON data into model classes in Flutter.
Top comments (0)