Safely unpacking JSON objects in Dart

Suragch
10 min readJun 30, 2021

Unpacking data the easy way with pattern matching

Updated Article

Updated July 4, 2023, for Dart 3.

My original article described the complexities of unpacking data from a JSON object. If you scroll down, you can still read that article. However, pattern matching in Dart 3 has greatly simplified the process.

The problem

You can unpack a raw JSON string using the dart:convert library like so:

import 'dart:convert';

void main() {
String rawJson = '{"name":"Mary","age":30}';
dynamic map = jsonDecode(rawJson);
String name = map['name'] as String;
int age = map['age'] as int;
Person person = Person(name, age);
}

class Person {
Person(this.name, this.age);
final String name;
final int age;
}

However, the code above makes a lot of assumptions while getting from jsonDecode to the Person object:

  • It assumes that map is a Map and not a List or a String.
  • It assumes the map has String keys.
  • It assumes that the map has a string key named name.
  • It assumes that the map has a string key named age.
  • It assumes the value of map['name'] is a String.
  • It assumes the value of map['age'] is an int.

Of course, you can see here that these assumptions are correct, but often the data is coming in from the internet. You can’t assume anything about data like that. And if any of your assumptions fail, Dart will throw an exception.

Now you could check all of those assumptions with lots of if statements, but there’s an easier way.

Pattern matching

Dart 3 introduced pattern matching that makes it easy to validate the structure of JSON data. Take a look at the code using pattern matching:

dynamic map = jsonDecode(rawJson);
if (map case {'name': String name, 'age': int age}) {
Person person = Person(name, age);
}

This is the new if-case statement. It takes the following form:

if (myObject case somePattern) => doSomething();

--

--