Flutter: Handle JSON Deep Dive

Varun Verma
9 min readDec 5, 2020

--

Handling the JSON in flutter may be a tricky task for beginners. So here I am explaining in deep how to handle the JSON in your application with no Fear. So let’s get started.

Started
Photo by Dayne Topkin on Unsplash

We started with simple JSON String and try to map it with our Model class. Let’s assume we have a profile type simple JSON file like that.

Assume you hit the an API call like below.(I already assume the you know about API calls and know GET POST requests)

getData() async{
http.Response response = await http.get("url");
var result = json.decode(response.body);
print(result);
}

and you got the response like below.

Type 1(Simple JSON Object).

{
"id" : 1,
"first_name" : "Varun",
"last_name" : "Verma",
"email" : "rajputvarun591@gmail.com",
"address" : "Khatauli UttarPradesh India 251201",
"phone" : "+910000000000",
"height" : 157.58,
"is_active" : true
}

As you can see it is a simple JSON and it looks like a Map. To detect whether it is a Map or List just look very first enclosure. If it is a Curly Brace “{” then it will be a Map. If it is a Squire Bracket “[” then it will be treated as a List of Maps. So to handle this JSON response first you have to check all the parameters with their respective Data Types. For example in our JSON parameter “id” have the data type “Integer”. So the model my_profile.dart with variables declaration will look like.

class MyProfile{
int id;
String firstName;
String lastName;
String email;
String address;
String phone;
double height;
bool isActive;
}

As you can see here the Model class variable names and the JSON parameters are not same. and it should not be for following the naming convention rules given by Dart Language. but don’t worry will take care it in Mapping. So after declaration of variables we have to Map our Model variables with the response parameters. see the method fromJsonResp() in below code.

MyProfile.fromJsonResp(Map<String, dynamic> json)
: id = json["id"],
firstName = json["first_name"],
lastName = json["last_name"],
email = json["email"],
address = json["address"],
phone = json["phone"],
height = json["height"],
isActive = json["is_active"];

That’s it you have to do for Map your JSON object with your Model. to see the values of result just override toString() method in your Model class. and print the object with toString() method. like below.

Future getData() async{
http.Response response = await http.get("url");
var result = json.decode(response.body);
MyProfile myProfile = MyProfile.fromJsonResp(result);
print(myProfile.toString());
}
Photo by Clark Tibbs on Unsplash

OK if you got this point then you will find it was so easy. So let’s move to our JSON file again and add some complexity in it. assume that we have another object in our this JSON data for the parameter “address” like:

Type 2(JSON Object inside JSON object).

{
"id" : 1,
"first_name" : "Varun",
"last_name" : "Verma",
"email" : "rajputvarun591@gmail.com",
"address" : {
"district" : "Meerut",
"city" : "Khatauli",
"country" : "India",
"pin" : 251201
},

"phone" : "+910000000000",
"height" : 157.58,
"is_active" : true
}

One thing you always have to remember that how much JSON objects you found in the data that much classes(Models) you have to create. (no matter where is it in the data). So here we have JSON object inside JSON object, what we have to do is create another Model for that JSON object. with their parameters as class variables(with following naming convention). let’s create.

class Address {
String district;
String city;
String country;
int pin;

Address.fromJsonResp(Map<String, dynamic> json)
: district = json["district"],
city = json["city"],
country = json["country"],
pin = json["pin"];
}

And now our my_profile.dart file will look like

class MyProfile{
int id;
String firstName;
String lastName;
String email;
Address address;
String phone;
double height;
bool isActive;

MyProfile.fromJsonResp(Map<String, dynamic> json)
: id = json["id"],
firstName = json["first_name"],
lastName = json["last_name"],
email = json["email"],
address = Address.fromJsonResp(json["address"]),
phone = json["phone"],
height = json["height"],
isActive = json["is_active"];
}

as you can see now variable address has return type Address from another model class address.dart, and it’s variable is initialized with their respective fromJsonResp() method. for print the values override toString() methos in address.dart also and print the myprofile.dart object.

Type 3(List<dynamic> inside JSON object).

now assume that the user have multiple phone numbers and we have parameter “phone” as a List of Strings. like below:

{
"id" : 1,
"first_name" : "Varun",
"last_name" : "Verma",
"email" : "rajputvarun591@gmail.com",
"address" : {
"district" : "Meerut",
"city" : "Khatauli",
"country" : "India",
"pin" : 251201
},
"phone" : ["+910000000000", "+910000123456", "+910001234567", "+910012345678", "+910123456789"],
"height" : 157.58,
"is_active" : true
}

as you can see it is a List of String values but in mapping the JSON you have to assume data type dynamic List, and we will type cast it at the mapping time. now for this JSON our my_profile.dart file with be modified as.

1. class MyProfile{
2. int id;
3. String firstName;
4. String lastName;
5. String email;
6. Address address;
7. List<String> phone;
8. double height;
9. bool isActive;

10.MyProfile.fromJsonResp(Map<String, dynamic> json)
11. : id = json["id"],
12. firstName = json["first_name"],
13. lastName = json["last_name"],
14. email = json["email"],
15. address = Address.fromJsonResp(json["address"]),
16. phone = (json["phone"] as List<dynamic>).map((e) => e.toString()).toList(),
17. height = json["height"],
18. isActive = json["is_active"];
19.}

consider line no 7, I modified my variable return type with my desired and expected return type. List<String>. after that consider line no 16 where I initialize my variable with values. let’s talk about line no 16. I know first thing after seeing my JSON data is that I have a List in my object(no matter which type of data it has inside, it will always be treated as List<dynamic> by default).

So we have to first type cast our object as List<dynamic>, for using the .map((e) => “”) method of List. then we will type cast each element in string by e.toString() method. In the first phrase (json[“phone”] as List<dynamic>) I type cast my object to tell the compiler this object is a List<dynamic> so compiler let you do the things which can be do with a List. now map the list and cast each element into String as I do in second phrase .map((e) => e.toString()).toList().

Type 4(List<JSON Object> inside JSON object).

OK let’s head over to another JSON data which holds a List of JSON Objects inside a JSON object consider the parameter “experiences” in below JSON data.

{
"id" : 1,
"first_name" : "Varun",
"last_name" : "Verma",
"email" : "rajputvarun591@gmail.com",
"address" : {
"district" : "Meerut",
"city" : "Khatauli",
"country" : "India",
"pin" : 251201
},
"phone" : ["+910000000000", "+910000123456", "+910001234567"],
"height" : 157.58,
"is_active" : true,
"experiences" : [
{
"years" : 4,
"company" : "ABC Pvt Ltd",
"company_id" : 101,
"started_on" : "2020/02/02",
"ended_on" : "2020/02/02",
},
{
"years" : 5,
"company" : "DEF Pvt Ltd",
"company_id" : 102,
"started_on" : "2020/02/02",
"ended_on" : "2020/02/02",
},
{
"years" : 8,
"company" : "GHI Pvt Ltd",
"company_id" : 103,
"started_on" : "2020/02/02",
"ended_on" : "2020/02/02",
}
]

}

Here in the data the parameter “experiences” holds the List of JSON Objects . So I have earlier told you what you have to do when you see a new JSON object in the data ? Yes we have to make another class(Model) to handle this Object. So let’s do it. and match your code with below code.

class Experiences {
int years;
String company;
String companyId;
String startedOn;
String endedOn;

Experiences.fromJsonResp(Map<String, dynamic> json)
: years = json["years"],
company = json["company"],
companyId = json["company_id"],
startedOn = json["started_on"],
endedOn = json["ended_on"];
}

Are you guys thinking I have done the same, I have did before ? hmm.. But that’s wasn’t a List of JSON objects. now consider variable List<Experiences> experiences in my_profile.dart file.

class MyProfile {
int id;
String firstName;
String lastName;
String email;
Address address;
List<String> phone;
double height;
bool isActive;
List<Experiences> experiences;

MyProfile.fromJsonResp(Map<String, dynamic> json)
: id = json["id"],
firstName = json["first_name"],
lastName = json["last_name"],
email = json["email"],
address = Address.fromJsonResp(json["address"]),
phone = (json["phone"] as List<dynamic>).map((e) => e.toString()).toList(),
height = json["height"],
isActive = json["is_active"],
experiences = (json["experiences"] as List<dynamic>).map((e) => Experiences.fromJsonResp(e)).toList();
}

and this is done for the variable experiences . for see the values repeat the same procedure override toString() method and print the object of my_profile.dart.

Let’s have a real type of JSON Object from the API and will try to handle it for more clarity. consider below JSON response from an weather API.

{
"status": "success",
"msg": "fetched",
"data": {
"text": "Poor",
"alert": "Poor air quality index in this location. It may cause breathing discomfort to people on prolonged exposure, and discomfort to people with heart disease.",
"color": "#FF9A00;",
"value": 300,
"index": 4,
"updated": "Thu Dec 03 06:15:00 +0000 2020",
"temp": "23",
"content": null,
"country": "India",
"image": "https://api.com/images/icons/50d.png",
"coordinates": {
"latitude": 28.704059,
"longitude": 77.10249
},
"source": {
"name": "CPCB, Mundka, Delhi DPCC",
"coordinates": {
"latitude": 28.684678,
"longitude": 77.076574
}
},
"accuracy": "3.32 Km",
"dominating": "PM2.5",
"aqiParams": [
{
"name": "NO2",
"value": "35.7 µg/m³, AQI 44",
"aqi": 44,
"color": "#bbcf4c;",
"text": "Satisfactory",
"updated": "Thu Dec 03 06:15:00 +0000 2020"
},
{
"name": "PM2.5",
"value": "186.0 µg/m³, AQI 300",
"aqi": 300,
"color": "#A52A2A;",
"text": "Severe",
"updated": "Thu Dec 03 06:15:00 +0000 2020"
},
{
"name": "SO2",
"value": "22.4 µg/m³, AQI 22",
"aqi": 22,
"color": "#79bc6a;",
"text": "Good",
"updated": "Thu Dec 03 06:15:00 +0000 2020"
},
{
"name": "PM10",
"value": "280.0 µg/m³, AQI 230",
"aqi": 230,
"color": "#FFCF00;",
"text": "Moderate",
"updated": "Thu Dec 03 06:15:00 +0000 2020"
},
{
"name": "CO",
"value": "1200.0 µg/m³, AQI 60",
"aqi": 60,
"color": "#A52A2A;",
"text": "Severe",
"updated": "Thu Dec 03 06:15:00 +0000 2020"
},
{
"name": "Humidity",
"value": "38.0 %",
"aqi": null,
"color": null,
"text": null,
"updated": null
},
{
"name": "Barometric Pressure",
"value": "1015.0 hPa",
"aqi": null,
"color": null,
"text": null,
"updated": null
},
{
"name": "Wind Speed",
"value": " 3.36 m/s",
"aqi": null,
"color": null,
"text": null,
"updated": null
},
{
"name": "Wind Direction",
"value": "270.0 degrees",
"aqi": null,
"color": null,
"text": null,
"updated": null
}
]
}
}

when you will minimize the all parameters of the outer object. you will see its has only three parameters like below.

Outer JSON Object

So the real time Object will look like. here you can see it has only three parameters in outer object so its unnecessary to create separate Model for this outer object. we consider our main object from the parameter “data”. but the question is how we will directly access “data” parameter. suppose you hit below API and got this response.

http.Response response = await http.get("url");
var result = json.decode(response.body);
if(result["status"] == "success") {
var data = result["data"];
print(data);
}

here variable “result” contains our whole JSON data. which has three parameters (success, message, data). To access the value of parameters will write like. result[“status”] for “status” parameter value. result[“message”] for access “message” parameter value and result[“data”] for access “data ”parameter value without create a Model class. if we will print result[“status”] will give us “success”.

Notes & Tips

  1. Whenever you not sure about the value of an parameter(some parameters having “null ”value) then you may confuse to declare Data Type of variable in Model class . then simply take var instead of any data type. consider below.

here the parameter “content” having the value null so can’t sure in future what type of value it will be hold. so in Model class when you declare the variable then take return type var.

OK guys that was the brief of JSON in flutter and dart. also i want to tell you it was my first article on medium so if i had made any mistake kindly refer it to me. Thank you and Happy coding. Bye.. Bye..

--

--