Json Serialisation in Flutter
In this article, we’re going to talk about serialising and deserialing an object to/from JSON in Flutter/Dart.
JSON serialisation in Dart uses the dart:convert
package for basic conversion functions and the json_serializable
package to generate serialisation and deserialisation helper functions.
Check out a complete example on GitHub: minibuildsio/flutter_json_serialisation_example.
Dependencies
We need to add the following regular and dev dependencies. json_annotation
provides the annotations that json_serializable
looks for and uses to generate the serialisation helper functions. build_runner
is the standard Dart package for code generation.
dependencies:
json_annotation: ^4.8.1
dev_dependencies:
json_serializable: ^6.7.1
build_runner: ^2.4.8
Find the latest versions: json_annotation, json_serializable, build_runner.
Using the JsonSerializable annotation
In the example below we have created WeatherData a class with a couple of fields of different types. The class has been annotated with @JsonSerializable()
which json_serializable
searches for and generates
The part directive, part 'model.g.dart'
, tells build_runner
where to put the generated code.
import 'package:json_annotation/json_annotation.dart';
part 'model.g.dart'
enum WeatherType {
sunny, rainy
}
@JsonSerializable()
class WeatherData {
final DateTime date;
final double temperature;
final WeatherType weatherType;
WeatherData(this.date, this.temperature, this.weatherType);
}
Generating helper functions
With the class annotated we can now use build_runner
to generate the helper functions using the command below:
dart run build_runner build
This will generate two functions in the model.g.dart
file _$WeatherDataFromJson
and _$WeatherDataToJson
. These functions convert from a Map<String, dynamic>
to a String
and vice versa. The dart:convert
package provided the functions jsonDecode
and jsonEncode
to convert objects to maps and vice versa.
We can put all this together in a factory function fromJson
and function toJson
.
factory WeatherData.fromJson(String json) => _$WeatherDataFromJson(jsonDecode(json));
String toJson() => jsonEncode(_$WeatherDataToJson(this));
The complete class
The complete class with the fromJson and toJson functions looks like this:
import 'dart:convert';
import 'package:json_annotation/json_annotation.dart';
part 'model.g.dart';
enum WeatherType {
sunny, rainy
}
@JsonSerializable()
class WeatherData {
final DateTime date;
final double temperature;
final WeatherType weatherType;
WeatherData(this.date, this.temperature, this.weatherType);
factory WeatherData.fromJson(String json) => _$WeatherDataFromJson(jsonDecode(json));
String toJson() => jsonEncode(_$WeatherDataToJson(this));
}
Using the toJson and fromJson functions
With those functions defined, you can use them like so:
final weatherDataString = WeatherData(
DateTime(2024, 3, 1, 12, 0, 0), 15.6, WeatherType.sunny
).toJson();
final weatherData = WeatherData.fromJson(
'{"date": "2024-02-29T12:00:00", "temperature": 12.4, "weatherType": "rainy"}'
);
Configuration and customisation
Often you’ll need to handle field names that are snake_case for example instead of camelCase. Annotations can be used to customise the serialisation, for example, the @JsonKey
can be used to rename a field.
@JsonKey(name: 'weather_type')
final WeatherType weatherType;
Note you will need to re-run the code generation, dart run build_runner build
, after any changes to the class.