If you're developing a Flutter application (or any application using Dart language) and you need to convert (serialize or stringify) a Dart object to JSON object or string, you come to the right place. In this tutorial, I'm going to show you from example with simple object and then continued with a complex object with nested structure.
Simple Class with Array of Primitive Types
As for example, we have a class Item
as the following.
class Item {
int id;
String name;
List<String> locations;
double price;
int stock;
bool active;
}
To get the JSON object of an Item
instance, you need to implement toJson
method which returns Map<String, dynamic>
. Inside, for every key you want to present on the JSON object, choose which property of the class you want to use. Here is the implementation of toJson.
class Item {
int id;
String name;
List<String> locations;
double price;
int stock;
bool active;
Map<String, dynamic> toJson() => _itemToJson(this);
}
Map<String, dynamic> _itemToJson(Item instance) {
return <String, dynamic>{
'id': instance.id,
'name': instance.name,
'locations': instance.locations,
'price': instance.price,
'stock': instance.stock,
'active': instance.active,
};
}
Here's the usage example of toJson()
. To get the value of a JSON key, use `[key-name]`, while for converting the JSON to a string, use toString()
on the JSON object.
Item item = new Item(
id: 1,
name: 'Item1',
locations: ['Abcde', '12345'],
price: 100.00,
stock: 10,
active: true,
);
Map<String, dynamic> itemJson = item.toJson();
print(itemJson['name']);
print(itemJson.toString());
Nested Class
Now the Item
class has a new property: dimensions
whose type is Dimensions
.
class Dimensions {
double width;
double depth;
double height;
Dimensions({this.width, this.depth, this.height});
}
You cannot simply add 'dimensions': instance.dimensions
inside toJson(). You need to implement another toJson()
method for the Dimensions
class.
class Dimensions {
double width;
double depth;
double height;
Dimensions({this.width, this.depth, this.height});
Map<String, dynamic> toJson() => _dimensionsToJson(this);
}
Map<String, dynamic> _dimensionsToJson(Dimensions instance) => <String, dynamic>{
'width': instance.width,
'depth': instance.depth,
'height': instance.height,
};
Then, modify _itemToJson
to use Dimensions
' toJson()
method. Beforehand, you need to check if the dimensions
value is not null
.
Map<String, dynamic> _itemToJson(Item instance) {
Map<String, dynamic> dimensions = instance.dimensions != null
? instance.dimensions.toJson()
: null;
return <String, dynamic>{
// Other properties
'dimensions': dimensions,
};
}
In case the inner class also has another inner class, you need to implement another toJson
- do it recursively until you don't find nested class.
Class with Array of Nested Class
Let's say the Item
class has a new property purchases
whose type is List<Purchase>
. How to handle this kind of structure?
First, you have to create toJson
method for the Purchase class
.
class Purchase {
int amount;
String customerName;
Purchase({this.amount, this.customerName});
Map<String, dynamic> toJson() => _purchaseToJson(this);
}
Map<String, dynamic> _purchaseToJson(Purchase instance) => <String, dynamic>{
'amount': instance.amount,
'customerName': instance.customerName,
};
Then, use map
on purchases
property. For each element, returns the JSON object by using Purchase
's toJson
method. Then, convert the map result to List<Map<String, dynamic>>
by using toList()
.
Map<String, dynamic> _itemToJson(Item instance) {
List<Map<String, dynamic>> purchases = instance.purchases != null
? instance.purchases.map((i) => i.toJson()).toList()
: null;
return <String, dynamic>{
// Other properties
'purhcases': purchases,
};
}
That's how to serialize a Dart object to JSON object or string. If you want to convert in the opposite way, you can read our tutorial about how to deserialize JSON string to object in Dart.