If you’re coming from an Android background like me then you’ve probably missed those POJO classes in Flutter. I believe the developers who do app development in flutter will encounter such problems. After requesting data from the server, the server will often return a json string and if we want to use data flexibly, we need to convert the json string into an object .

Since flutter only provides json to Map . Handwritten deserialization is extremely unstable in large projects and can easily lead to parsing failure. So today I will introduce you to json_annotation, an automatic deserialization library recommended by flutter team.

What you’ll learn

Generate code with build_runner .

. How to parse json object in the flutter with json_serialization .

Include Dependencies

We’re gonna need to add some libraries in the pupspec.yaml , which is the package management and build system file. Here we need to add three dependencies json_annotation , build_runner and json_serializable in the pupspec.yaml file.

dependencies: flutter: sdk: flutter # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^0.1.2 json_annotation: ^1.2.0 // dependecy dev_dependencies: flutter_test: sdk: flutter build_runner: ^1.0.0 // | // | -> dev dependencies json_serializable: ^1.5.1 // |

Once you have done these run packets get which is in the toolbar of the file from IntelliJ/Android Studio you can also execute flutter packages pub get from the terminal in the current project directory if you prefer that.

Now let’s say we need to make a login request and download some json content. The following shows the sample json of a simplified login rest call.

{ "status" : true, "message" : "User successfuly logged in!", "user_name" : "Ahsen Saeed", "profile_url" : "www.codinginfinite.com", "user_id" : 280 }

Now we need to write a dart entity class based on above json data.

class LoginResponse{ bool status; String message; String userName; String profileUrl; int userId; LoginResponse(this.status,this.message,this.userName,this.profileUrl,this.userId); factory LoginResponse.fromJson(map<String,dynamic> json) { return LoginResponse( status : json['status'], message : json['message'], userName : json['user_name'], profileUrl : json['profile_url'], userId : json['user_id'] ) } }

I know, I know, I just want to show you guys, the manual deserialization before showing the auto-generated json deserialization.

Generate an auto-generated json File

The following shows the JsonSerializer model of above json.

import 'package:json_annotation/json_annotation.dart'; @JsonSerializable() class LoginResponse { bool status; String message; @JsonKey(name: 'user_name') String userName; @JsonKey(name: 'profile_url') String profileUrl; @JsonKey(name: 'user_id') int userId; LoginResponse( this.status, this.message, this.userName, this.profileUrl, this.userId); }

If we want to use JsonSerializer to generate code, we must add the annotation @JsonSerializable() before the signature of class that needs to generate the code and if you need to define the name case of the member, use the @JsonKey annotation.

So, the question is how should the code be generated..? If you guys have remembered that we add the build_runner dependency in our pupspec.yaml file.

So, in order to generate the Pojo class for a LoginResponse run the following command in the current project directory

flutter packages pub run build_runner build

After the command runs successfully, we should be able to find a new file under the entity file.

The models.g.dart json parsing file generated by build_runner based on JsonSerializer . Below is the generated dart file.

// ************************************************************************** // JsonSerializableGenerator // ************************************************************************** LoginResponse _$LoginResponseFromJson(Map<String, dynamic> json) { return LoginResponse( json['status'] as bool, json['message'] as String, json['user_name'] as String, json['profile_url'] as String, json['user_id'] as int); } Map<String, dynamic> _$LoginResponseToJson(LoginResponse instance) => <String, dynamic>{ 'status': instance.status, 'message': instance.message, 'user_name': instance.userName, 'profile_url': instance.profileUrl, 'user_id': instance.userId };

Now we only need to associate our generated file in our entity class and provide a way to parse the json in the entity class. Let’s see how we can associate the generated file with our generated file.

import 'package:json_annotation/json_annotation.dart'; part 'package:flutter_projects/models/models.g.dart'; // associated generated dart file @JsonSerializable() class LoginResponse { bool status; String message; @JsonKey(name: 'user_name') String userName; @JsonKey(name: 'profile_url') String profileUrl; @JsonKey(name: 'user_id') int userId; LoginResponse(this.status, this.message, this.userName, this.profileUrl, this.userId); factory LoginResponse.fromJson(Map<String, dynamic> json) => _$LoginResponseFromJson(json); }

In order for the entity class file to find the generated file, we need part and let the entity class to mix with the generated file. Finally, a factory constructor is provided, which actually calls _$LoginResponseFromJson the method of the generated file. The _$LoginResponseFromJson method is the one who deserializes our json. And that’s how we can simply deserialize our json into dart object.

Let’s take another example where we have a user json and within that user object, we have subjects of a user. Let’s see the json first.

{ "status" : true, "message" : "User successfuly logged in!", "user_name" : "Ahsen Saeed", "profile_url" : "www.codinginfinite.com", "user_id" : 280, "subjects" : [ { "subject_name" : "ComputerProgramming" }, { "subject_name" : "Calculus" } ] }

You see in order to parse the above json, we need to add a list of subjects in our LoginResponse model.

@JsonSerializable() class LoginResponse { bool status; String message; @JsonKey(name: 'user_name') String userName; @JsonKey(name: 'profile_url') String profileUrl; @JsonKey(name: 'user_id') int userId; @JsonKey(name: 'subjects') List<Subject> subjects; LoginResponse(this.status, this.message, this.userName, this.profileUrl, this.userId, this.subjects); factory LoginResponse.fromJson(Map<String, dynamic> json) => _$LoginResponseFromJson(json); } @JsonSerializable() class Subject { @JsonKey(name: 'subject_name') String subjectName; Subject(this.subjectName); factory Subject.fromJson(Map<String, dynamic> json) => _$SubjectFromJson(json); }

Finally, below is the newly generated file.

// ************************************************************************** // JsonSerializableGenerator // ************************************************************************** LoginResponse _$LoginResponseFromJson(Map<String, dynamic> json) { return LoginResponse( json['status'] as bool, json['message'] as String, json['user_name'] as String, json['profile_url'] as String, json['user_id'] as int, (json['subjects'] as List) ?.map((e) => e == null ? null : Subject.fromJson(e as Map<String, dynamic>)) ?.toList()); } Map<String, dynamic> _$LoginResponseToJson(LoginResponse instance) => <String, dynamic>{ 'status': instance.status, 'message': instance.message, 'user_name': instance.userName, 'profile_url': instance.profileUrl, 'user_id': instance.userId, 'subjects': instance.subjects }; Subject _$SubjectFromJson(Map<String, dynamic> json) { return Subject(json['subject_name'] as String); } Map<String, dynamic> _$SubjectToJson(Subject instance) => <String, dynamic>{'subject_name': instance.subjectName};

I hope this article, gives you a good understanding of how to deserialize the json with json_annotation library into plain old dart object. If you’ve enjoyed this story, share this article with flutter community.

Thank you for being here and keep reading…