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?
Understanding JSON
JSON is just a text format that most REST APIs use to return their data. Another common format is XML, but XML is quite a bit more verbose.
Here’s a small example of JSON:
{
"user": {
"name": "Kevin Moore",
"occupation": "Programmer"
}
}
Notice that the snippet starts with a brace {
, which indicates an object. JSON can also start as an array, which uses the square bracket [
symbol to signify the start of the array. JSON needs to be properly formatted, so all beginning {
and [
symbols need to have their ending symbols: }
and ]
.
Once you have downloaded a JSON string, you can do a few different things:
- Keep it as a string and parse out the key/value pairs.
- Convert the string to a Dart
Map
from which you can get the key/value pairs. - Convert the string to Dart model objects from which you can get the values from the object properties.
All of these options have different pros and cons. Dealing with a string can get complicated if you have a lot of data. Using Map
values can make the code quite verbose. Converting to model objects takes more work, but is easier to use.
We’ll prefer the model object approach below.
Parsing JSON
There are a few different ways that you can parse JSON code.
By Hand
You can parse a JSON string by hand by using the dart:convert
library.
Here’s an example:
import 'dart:convert';
Map<String, dynamic> user = jsonDecode(jsonString);
var name = user['user]['name'];
This doesn’t look too hard, but if you start working with complex JSON strings, it becomes very tedious to write and maintain.
Using Libraries
If you go to Pub.dev, a repository of Dart packages, and search for JSON Flutter libraries, you’ll find several libraries for dealing with JSON. For this tutorial, you’ll be using two Flutter libraries:
- HTTP for network calls, as seen above.
- json_annotation for annotating your JSON model classes.
You’ll also use two development libraries that create helper classes for converting JSON strings into your model objects:
- build_runner, which runs your json_serializable library.
- json_serializable, which creates the extra helper classes that convert strings into your models.
These two libraries will go into the dev_dependencies section of your pubspec.yaml.
To add them, start by opening pubspec.yaml in the root of the project. First, you’ll add the Flutter libraries.
In the dependencies
section, add the json_annotation dependency underneath http:
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^0.1.2
http: ^0.12.0+2
json_annotation: ^2.0.0
Next, go to the dev_dependencies
section and add the build_runner and json_serializable dependencies:
dev_dependencies:
flutter_test:
sdk: flutter
build_runner: ^1.0.0
json_serializable: ^2.0.0
Next, press the Packages get prompt that shows up in the top-right side of the Android Studio. If you have any problems, make sure you line up the dependecies to match what you see in the final project, since YAML file formatting is very strict.
The Cat API
Now, open cats_api.dart in the lib/api folder. The first line is a constant called apiKey
. Replace Your Key with the key you obtained from the Cat API site, then take a look at the code:
const String apiKey = 'Your Key';
//1
const String catAPIURL = 'https://api.thecatapi.com/v1/breeds?';
// 2
const String catImageAPIURL = 'https://api.thecatapi.com/v1/images/search?';
// 3
const String breedString = 'breed_id=';
// 4
const String apiKeyString = 'x-api-key=$apiKey';
class CatAPI {
// 5
Future<dynamic> getCatBreeds() async {
// 6
Network network = Network('$catAPIURL$apiKeyString');
// 7
var catData = await network.getData();
return catData;
}
// 8
Future<dynamic> getCatBreed(String breedName) async {
Network network =
Network('$catImageAPIURL$breedString$breedName&$apiKeyString');
var catData = await network.getData();
return catData;
}
}
Here’s what you see:
- A string value of the API to get the list of breeds.
- A string URL for running a cat image search.
- A string to capture the actual breed ID.
- A string that uses your API key to add to the final URL.
- A method
getCatBreeds()
to return the breed data. - Use of your Network class from above to pass in your breed’s API string and your key.
- Awaiting the asynchronous result.
- A method
getCatBreed(String breedName)
to get the cat image for a given breed.
Using the Cat API
Open cat_breeds.dart in the lib/screens folder.
Inside _CatBreedsPageState
, add the following:
void getCatData() async {
var result = await CatAPI().getCatBreeds();
print(result);
}
This method calls the cat API to get the cat breeds.
You’ll need to import the CatAPI
class from cat_info.dart. You can do that manually or, if you like, put the cursor over the call to the CatAPI
constructor and press Option + Enter and choose Import.
Next, call the new method you’ve added to get the cat data by adding the following to the bottom of initState()
:
getCatData();
Now, run your app to check if your connection to the API works. Take a look at the output in the run tab and you should see the JSON string printed out.
Now that your your initial call to the Cat API works, you’ll create the model classes you need in the next step.
Creating Models
Get started by opening cats.dart in the Models folder. You’ll see commented out an example of the JSON data returned by the API.
Add a class that describes a cat breed:
class Breed {
String id;
String name;
String description;
String temperament;
Breed({this.id, this.name, this.description, this.temperament});
}
This class defines the fields you’ll pull from the JSON. You need the id
to get the image of the cat breed. You’ll display name
and description
on the card view.
If you look at the data you printed to the console above, you’ll see that it starts with the square bracket [
character, meaning that you’ll get a JSON array of breeds. Add a class to hold that array of data now:
class BreedList {
List<Breed> breeds;
BreedList({this.breeds});
}
This class holds a Dart list of cat breeds.
For the image search, you need to describe the cat, the cat breed and the list of cat breeds, like so:
class Cat {
String name;
String description;
String life_span;
Cat({this.name, this.description, this.life_span});
}
class CatBreed {
String id;
String url;
int width;
int height;
List<Cat> breeds;
CatBreed({this.id, this.url, this.width, this.height, this.breeds});
}
class CatList {
List<CatBreed> breeds;
CatList({this.breeds});
}
Add those classes to cats.dart now.
For this tutorial, you won’t use the temperament or life_span fields, but you could use them if you wanted to enhance the app.