Parsing JSON in Flutter
Learn about getting and parsing JSON data from the internet when building a cross-platform app using Flutter. By Kevin D Moore.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Parsing JSON in Flutter
25 mins
- Getting Started
- Understanding the UI
- Using REST APIs
- Signing Up for a Cats API
- Making Network Calls
- Understanding JSON
- Parsing JSON
- By Hand
- Using Libraries
- The Cat API
- Using the Cat API
- Creating Models
- Using JSON Annotations
- JSON Conversion Methods
- Using build_runner
- Using the Models
- Building the Cat Detail Page
- Where to Go From Here?
Using JSON Annotations
Now you’ll use the json_annotation library to parse the JSON data into objects of your model classes.
Go to the top of cats.dart and add:
import 'package:json_annotation/json_annotation.dart';
part 'cats.g.dart';
The part
statement imports a file and allows you to use its private variables. You’ll see an error on this statement for now, until you later use build_runner to generate the file cats.g.dart.
Next, you need to add the @JsonSerializable()
annotation to each class. For example, your Breed
class should look like this when the annotation is added:
@JsonSerializable()
class Breed {
String id;
String name;
String description;
String temperament;
Breed({this.id, this.name, this.description, this.temperament});
}
Make sure you add the annotation before every class in cats.dart.
JSON Conversion Methods
In the next step, you’ll add some factory methods to each class. The build runner plugin will use these methods to create a Dart file that will do all the hard work of parsing the JSON data for you.
In the Breed
class add the following after the constructor:
factory Breed.fromJson(Map<String, dynamic> json) => _$BreedFromJson(json);
Map<String, dynamic> toJson() => _$BreedToJson(this);
Each class will include fromJson
and toJson
. These methods call the generated code that parses the JSON. At this point, you’ll notice some more errors in Android Studio. Don’t worry about those at the moment; you’ll clear them up later.
In BreedList
, add the following after the constructor:
factory BreedList.fromJson(List<dynamic> json) {
return BreedList(
breeds: json
.map((e) => Breed.fromJson(e as Map<String, dynamic>))
.toList());
}
This is the fromJson
you need to parse the JSON array to a list of breeds.
Add fromJson
and toJson
after the constructor in Cat
:
factory Cat.fromJson(Map<String, dynamic> json) => _$CatFromJson(json);
Map<String, dynamic> toJson() => _$CatToJson(this);
Next, after the constructor in CatBreed
, add:
factory CatBreed.fromJson(Map<String, dynamic> json) =>
_$CatBreedFromJson(json);
Map<String, dynamic> toJson() => _$CatBreedToJson(this);
Finally, add the following after the constructor in CatList
:
factory CatList.fromJson(List<dynamic> json) {
return CatList(
breeds: json
.map((e) => CatBreed.fromJson(e as Map<String, dynamic>))
.toList());
}
You’ve now added all the fromJson
and toJson
methods you need in your model classes.
Using build_runner
Your next step is to run the tool that generates the files that will parse the JSON. Open the Terminal
tab at the bottom of Android Studio, and enter the following:
flutter packages pub run build_runner build
When the command completes, if everything ran correctly, the errors you saw earlier in cats.dart should be gone, and you should now see cats.g.dart in the same directory as cats.dart. If you open cats.g.dart, you’ll notice methods for converting JSON to your model classes and back.
Using the Models
Now that you’ve created and generated your models, it’s time to put them to work.
Go back to cat_breeds.dart. In getCatData()
, you can now parse the JSON you got from the internet into your model classes.
To start, at the top of _CatBreedsPageState
, add a property for the breed list:
class _CatBreedsPageState extends State<CatBreedsPage> {
BreedList breedList = BreedList();
...
Import cats.dart at the top of the file to clear the errors you see.
In getCatData()
, add these lines after the print statement:
// 1
var catMap = json.decode(result);
// 2
setState(() {
// 3
breedList = BreedList.fromJson(catMap);
});
Here you:
- Use
json.decode(result)
to turn the JSON string into a map. - Call
setState
to rebuild your widget due to changes in the data. - Use
fromJson(catMap)
to convert the map into a list of breeds.
Be sure to import the dart:convert library for the json.decode()
statement. You have now converted your JSON data into a list of cat breeds!
But wait! You still need to get that list into the UI. How do you do that?
Since you have a list of cat breeds, what better way to display them than with a ListView
widget?
Go down to the body: ListView.builder
statement and replace the itemCount: 0
with:
itemCount: (breedList == null || breedList.breeds == null || breedList.breeds.length == 0) ? 0 : breedList.breeds.length,
This sets the itemCount
to the length of the breeds list.
Next, replace the title
and subtitle
of the ListTile
with the following:
title: Text(breedList.breeds[index].name),
subtitle: Text(breedList.breeds[index].description),
Now build and run the app and see how it looks. You should see a list of cat breed names and their descriptions.
Congratulations!
Building the Cat Detail Page
Your next step is to set up the onTap
listener so that tapping on a row shows the breed image.
Inside the Navigator.push
call of GestureDetector
in the ListView.Builder
, replace the call in the onTap()
with:
return CatInfo(catId: breedList.breeds[index].id, catBreed: breedList.breeds[index].name);
This adds the actual id
and name
of the tapped row into the constructor call for CatInfo
.
Now, open cat_info.dart in lib/screens. In _CatInfoState
, add the following above the initState
override:
CatList catList = CatList();
void getCatData() async {
var catJson = await CatAPI().getCatBreed(widget.catId);
print(catJson);
var catMap = json.decode(catJson);
print(catMap);
setState(() {
catList = CatList.fromJson(catMap);
});
}
Next, add a call to the getCatData()
method you added within initState
:
@override
void initState() {
super.initState();
getCatData();
}
Be sure to import all the class files you need.
Now, in getCat()
, after the mediaSize
property declaration, add:
if (catList == null ||
catList.breeds == null ||
catList.breeds.length == 0) {
return Container();
}
This will return an empty Container
if the list of cat breeds is null or empty.
In the return
statement for the non-empty Container
, after the height:
argument, add the following:
// 1
decoration: BoxDecoration(image: DecorationImage(
// 2
image: NetworkImage(catList.breeds[0].url),fit: BoxFit.contain,
)),
Here you have:
- BoxDecoration to let you draw an image in a box area.
- NetworkImage to load an image URL from the network.
Notice how you’re using a decoration to display a network image. You don’t have to do a thing, just wrap the cat URL in a NetworkImage
widget. Awesome, right? :]
Build and run your app and tap on any breed. You should now see cat images for each breed. Congratulations!
Where to Go From Here?
You can download the final completed project using the Download Materials button at the top or bottom of this tutorial.
Wow, that was a lot of work, but you learned:
- Using the HTTP library to issue network API requests.
- making API calls to return data.
- Parsing returned JSON into model classes.
- Displaying lists of items in a
ListView
. - Displaying a network image.
You can learn more about Flutter JSON parsing by visiting JSON and serialization in the Flutter docs and the docs for JSON Serializable.
Stay tuned for more Flutter tutorials and screencasts!
Feel free to share your feedback and findings or ask any questions in the comments below or in the forums. I hope you enjoyed learning about JSON parsing in Flutter!