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 objectobject .
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_runnerbuild_runner. - How to parse json object in the flutter with
json_serializationjson_serialization.
Include Dependencies
We’re gonna need to add some libraries in the pupspec.yamlpupspec.yaml, which is the package management and build system file. Here we need to add three dependencies json_annotationjson_annotation, build_runner build_runner
and json_serializable json_serializable in the pupspec.yamlpupspec.yamlfile.
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 // | Recommended for you
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 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 JsonSerializerJsonSerializer 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 JsonSerializerJsonSerializer to generate code, we must add the annotation @JsonSerializable()@ 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@JsonKey annotation.
So, the question is how should the code be generated..? If you guys have remembered that we add the build_runnerbuild_runner dependency in our pupspec.yamlpupspec.yaml file.
So, in order to generate the Pojo class for a LoginResponseLoginResponse 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_runnerbuild_runner based on JsonSerializerJsonSerializer. 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 partpart and let the entity class to mix with the generated file. Finally, a factory constructor is provided, which actually calls _$LoginResponseFromJson _$LoginResponseFromJson the method of the generated file. The _$LoginResponseFromJson _$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 LoginResponseLoginResponse 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…
Related Articles