Dart has built in support for parsing json. Given a String you can use the dart:convert
library and convert the Json (if valid json) to a Map with string keys and dynamic objects. You can parse json directly and use the map or you can parse it and put it into a typed object so that your data has more structure and it’s easier to maintain.
Direct Parsing and Usage
var jsonData = '{ "name" : "Dane", "alias" : "FilledStacks" }';
var parsedJson = json.decode(jsonData);
print('${parsedJson.runtimeType} : $parsedJson');
Running the code above will give you
_InternalLinkedHashMap<String, dynamic> : {name: Dane, alias: FilledStacks}
So the way you access your parsed data is by using key index on the returned map. Let’s index into the map and get the name and the alias out.
...
var name = parsedJson['name'];
var alias = parsedJson['alias'];
print('$name is $alias');
This will output.
Dane is FilledStacks
Parse Into Object
Instead of using the parsed data directly it’s common practice under programmers to put this data into a class that models your data for you. This is commonly done through a named constructor in Dart. Let’s put our test data into a model. We’ll define the model in the basic way first, then get to the named constructor.
class User {
String name;
String alias;
User(Map<String, dynamic> data) {
name = data['name'];
alias = data['alias'];
}
}
...
var jsonData = '{ "name" : "Dane", "alias" : "FilledStacks" }';
var parsedJson = json.decode(jsonData);
var user = User(parsedJson);
print('${user.name} is ${user.alias}');
This is doing the same as the raw access but it’s easier to read, understand and maintain. There’s also no String keys being used besides in the constructor. This way would be fine, but having only that one constructor limits you and does not leave your model open for extension. You’ll have to modify it to get any other functionality into it. Instead the common practice is to have a constructor that sets all the properties for you and use a named constructor to create a model explicitly using outside data.
class User {
final String name;
final String alias;
User({this.name, this.alias});
User.fromJson(Map<String, dynamic> data)
: name = data['name'],
alias = data['alias'];
}
...
var jsonData = '{ "name" : "Dane", "alias" : "FilledStacks" }';
var parsedJson = json.decode(jsonData);
var user = User.fromJson(parsedJson);
print('${user.name} is ${user.alias}');
This is neater, more explicit and your model is now less dependent on a Map being passed to it. One problem to think of is complex json that would require a complex model. Do you really want to type out all those fields for a simple model. I would do it because I think it’s better in the long run, but luckily we don’t have to. This exists
if for some reason this site is down one day. Just google json to dart converter and you’ll find a few of them even open source gitrepos that does it.
You paste your json on the left and get your models on the right. The root class is always called AutoGenerated so just name that to what you want. You also have the option to use private fields. This takes care of any json object creations you might need.
I hope this helped.
Checkout and subscribe to my Youtube Channel. Follow me on Instagram for snippets and day-to-day programming. Checkout all the other snippets here. You might find some more Flutter magic.