Parsing JSON in Flutter
Learn about getting and parsing JSON data from the internet when building a cross-platform app using Flutter. By Sardor Islomov.
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 the 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
- Error Handling
- 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": "Sardor Islomov",
"occupation": "Software Engineer"
}
}
Notice that the snippet starts with a brace {
, which indicates an object. JSON can also start as an array, which uses the square bracket [
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’ve 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 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.
You’ll use the model object approach below.
Parsing JSON
You can parse JSON code in a few different ways.
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 use 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: ^1.0.5
http: ^0.13.6
json_annotation: ^4.8.1
Next, go to the dev_dependencies
section and add the build_runner
and json_serializable
dependencies:
dev_dependencies:
flutter_test:
sdk: flutter
build_runner: ^2.4.4
json_serializable: ^6.7.0
Next, press the Packages get or the Pub 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 dependencies 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 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<String> getCatBreeds() async {
// 6
final network = Network('$catAPIURL$apiKeyString');
// 7
final catData = await network.getData();
return catData;
}
// 8
Future<String> getCatBreed(String breedName) async {
final network =
Network('$catImageAPIURL$breedString$breedName&$apiKeyString');
final catData = await network.getData();
return catData;
}
}
Here’s what you see:
- A string value of the API to get the list of breeds.
- The 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.
- The 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 {
final catJson = await CatAPI().getCatBreeds();
print(catJson);
}
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, press Option-Enter and choose Import.
Next, call the new method you’ve added to get the cat data by modifying initState()
to the following:
@override
void initState() {
super.initState();
getCatData();
}
Now, run/restart your app to check if your connection to the API works. Look at the output in the run tab, and you’ll see the JSON string printed out:
Now that 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 lib/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({
required this.id,
required this.name,
required this.description,
required 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.
Look at the data you printed to the console above, and you’ll see that it starts with the square bracket [
character, meaning you’ll get a JSON array of breeds. Add a class to hold that array of data now:
class BreedList {
List<Breed> breeds;
BreedList({required 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. Add the classes below to cats.dart:
class Cat {
String name;
String description;
String life_span;
Cat({required this.name,required this.description,required this.life_span});
}
class CatBreed {
String id;
String url;
int width;
int height;
CatBreed({
required this.id,
required this.url,
required this.width,
required this.height
});
}
class CatList {
List<CatBreed> breeds;
CatList({required this.breeds});
}
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.