Since Flutter took out dart: mirrors off of its SDK, it's no longer possible to use libraries like dartson for JSON to object serialization/deserialization. However I've read that built_value is another way of achieving a similar purpose. I couldn't find any good examples on how to implement it as it contains a significant amount of boilerplate code. Can someone give me an example? For instance, this is the JSON I'm trying to serialize to objects:
{
"name":"John",
"age":30,
"cars": [
{ "name":"Ford", "models":[ "Fiesta", "Focus", "Mustang" ] },
{ "name":"BMW", "models":[ "320", "X3", "X5" ] },
{ "name":"Fiat", "models":[ "500", "Panda" ] }
]
}
JSON serialization with code generation means having an external library generate the encoding boilerplate for you. After some initial setup, you run a file watcher that generates the code from your model classes. For example, json_serializable and built_value are these kinds of libraries.
The JSON (JavaScript Object Notation) is a kind of data format that encodes an object into a string. This kind of data can be easily translated between server and browser, and server to server. Serialization is a process that converts an object into the same string.
I was hoping for more details from the answers provided. Even though they were good suggestions, they were too general for me to understand. So after doing my own research, I'll share my implementation to the above JSON example I provided in hope that it would save someone's else's time. So here are the steps I followed:
dependencies:
built_value: ^1.0.1
built_collection: ^1.0.0dev_dependencies:
build_runner: ^0.3.0
built_value_generator:^1.0.1
build.dart
// Copyright (c) 2015, Google Inc. Please see the AUTHORS file for details.
// All rights reserved. Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
import 'dart:async';
import 'package:build_runner/build_runner.dart';
import 'package:built_value_generator/built_value_generator.dart';
import 'package:source_gen/source_gen.dart';
/// Example of how to use source_gen with [BuiltValueGenerator].
///
/// Import the generators you want and pass them to [build] as shown,
/// specifying which files in which packages you want to run against.
Future main(List<String> args) async {
await build(
new PhaseGroup.singleAction(
new GeneratorBuilder([new BuiltValueGenerator()]),
new InputSet('built_value_example', const [
'lib/model/*.dart',
'lib/*.dart',
])),
deleteFilesByDefault: true);
}
watch.dart
// Copyright (c) 2016, Google Inc. Please see the AUTHORS file for details.
// All rights reserved. Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
import 'dart:async';
import 'package:build_runner/build_runner.dart';
import 'package:built_value_generator/built_value_generator.dart';
import 'package:source_gen/source_gen.dart';
/// Example of how to use source_gen with [BuiltValueGenerator].
///
/// This script runs a watcher that continuously rebuilds generated source.
///
/// Import the generators you want and pass them to [watch] as shown,
/// specifying which files in which packages you want to run against.
Future main(List<String> args) async {
watch(
new PhaseGroup.singleAction(
new GeneratorBuilder([new BuiltValueGenerator()]),
new InputSet('built_value_example', const [
'lib/model/*.dart',
'lib/*.dart'])),
deleteFilesByDefault: true);
}
serializers.dart
library serializers;
import 'package:built_collection/built_collection.dart';
import 'package:built_value/serializer.dart';
import 'package:built_value/standard_json_plugin.dart';
import 'model/person.dart';
part 'serializers.g.dart';
Serializers serializers = (
_$serializers.toBuilder()..addPlugin(new StandardJsonPlugin())
).build();
person.dart
library person;
import 'package:built_collection/built_collection.dart';
import 'package:built_value/built_value.dart';
import 'package:built_value/serializer.dart';
part 'person.g.dart';
abstract class Person implements Built<Person, PersonBuilder> {
String get name;
int get age;
BuiltList<Car> get cars;
Person._();
factory Person([updates(PersonBuilder b)]) = _$Person;
static Serializer<Person> get serializer => _$personSerializer;
}
abstract class Car implements Built<Car, CarBuilder> {
String get name;
BuiltList<String> get models;
Car._();
factory Car([updates(CarBuilder b)]) = _$Car;
static Serializer<Car> get serializer => _$carSerializer;
}
After creating the 4 files above, it will show some compiler errors. Don't mind them yet. This is because the build.dart file hasn't been run yet. So in this step, run build.dart. If you're using Webstorm, simply right click on build.dart and hit "Run build.dart". This will create 2 files: "person.g.dart" and "serializers.g.dart". If you notice carefully, in our build.dart file, we put 'lib/model/.dart' and 'lib/.dart'. The build knows where to look for those files by going through the paths specified and looks for files which have part "something" included. So it's important to keep that line in those files before running the build.dart file
Finally, now I can use the serializer in my main.dart file to serialize the json string to my custom dart object class Person. In my main.dart, I added the following code in initState()
main.dart
Person _person;
@override
void initState() {
super.initState();
String json = "{"
"\"name\":\"John\",\"age\":30,\"cars\": "
"["
"{ \"name\":\"Ford\", \"models\":[ \"Fiesta\", \"Focus\", \"Mustang\" ] },"
"{ \"name\":\"BMW\", \"models\":[ \"320\", \"X3\", \"X5\" ] },"
"{ \"name\":\"Fiat\", \"models\":[ \"500\", \"Panda\" ] }"
"]}";
setState(() {
_person = serializers.deserializeWith(
Person.serializer, JSON.decode(json));
});
}
My sample project is also available on Github Built value sample project
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With