Flutter Dart Serialization

Serialization plays a crucial role in app development, enabling efficient storage, transmission, and retrieval of data. When it comes to Flutter, the Dart language is the key to handling serialization effectively. In this article, we will dive into the fundamentals of Flutter Dart serialization, providing you with example codes and easy ways to implement serialization in your Flutter projects. Whether you’re a beginner or an intermediate Flutter developer, this friendly guide will empower you to manage your app’s data with ease.

Understanding Basic Serialization Concepts

Serialization refers to the process of converting data structures or objects into a format that can be stored or transmitted. One of the most popular serialization formats is JSON (JavaScript Object Notation). In the context of Flutter, Dart provides built-in support for JSON serialization, making it seamless to work with data models.

At its core, serialization involves converting objects or data structures into a format that can be easily serialized and deserialized. Serialization allows you to convert complex data into a structured format that can be saved, sent over a network, or shared across platforms. On the other hand, deserialization is the process of reconstructing objects from the serialized data.

Serialization in Dart

To get started with Flutter Dart serialization, let’s set up a Flutter project. We will explore two approaches: one without using any external packages and another using a popular third-party package called json_serializable.

Approach 1: Without using packages

In this approach, we will utilize Dart’s built-in JSON serialization support.

class User {
  final int id;
  final String name;
  final String email;

  User(this.id, this.name, this.email);

  Map<String, dynamic> toJson() {
    return {
      'id': id,
      'name': name,
      'email': email,
    };
  }

  factory User.fromJson(Map<String, dynamic> json) {
    return User(
      json['id'],
      json['name'],
      json['email'],
    );
  }
}

void main() {
  // Serialization
  User user = User(1, 'John Doe', 'john.doe@example.com');
  Map<String, dynamic> json = user.toJson();
  String jsonString = jsonEncode(json);
  print(jsonString);

  // Deserialization
  Map<String, dynamic> parsedJson = jsonDecode(jsonString);
  User deserializedUser = User.fromJson(parsedJson);
  print(deserializedUser.name);
}

Approach 2: Using the json_serializable package

The json_serializable package eliminates the manual effort of writing serialization code by automatically generating it based on annotations.

Step 1: Add the json_serializable package to your pubspec.yaml file:

dependencies:
  flutter:
    sdk: flutter
  json_annotation: ^4.4.0
  json_serializable: ^4.1.4

Step 2: Run flutter pub get to fetch the package.

Step 3: Create a data model class and annotate it with @JsonSerializable:

import 'package:json_annotation/json_annotation.dart';

part 'user.g.dart';

@JsonSerializable()
class User {
  final int id;
  final String name;
  final String email;

  User(this.id, this.name, this.email);

  factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
  Map<String, dynamic> toJson() => _$UserToJson(this);
}

Step 4: Generate serialization code by running the following command in your terminal:

flutter pub run build_runner build

Step 5: Utilize the generated serialization code:

import 'dart:convert';

void main() {
  // Serialization
  User user = User(1, 'John Doe', 'john.doe@example.com');
  String jsonString = jsonEncode(user.toJson());
  print(jsonString);

  // Deserialization
  Map<String, dynamic> json = jsonDecode(jsonString);
  User deserializedUser = User.fromJson(json);
  print(deserializedUser.name);
}

Handling nested objects and complex data structures

Dart’s JSON serialization support handles nested objects and complex data structures seamlessly. You can define relationships between objects and use the appropriate annotations to ensure proper serialization and deserialization.

Consider a scenario where a User has a nested Address object:

@JsonSerializable()
class Address {
  final String street;
  final String city;
  final String state;

  Address(this.street, this.city, this.state);

  factory Address.fromJson(Map<String, dynamic> json) => _$AddressFromJson(json);
  Map<String, dynamic> toJson() => _$AddressToJson(this);
}

@JsonSerializable()
class User {
  final int id;
  final String name;
  final String email;
  final Address address;

  User(this.id, this.name, this.email, this.address);

  factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
  Map<String, dynamic> toJson() => _$UserToJson(this);
}

void main() {
  // Serialization
  Address address = Address('123 Main St', 'Cityville', 'Stateville');
  User user = User(1, 'John Doe', 'john.doe@example.com', address);
  String jsonString = jsonEncode(user.toJson());
  print(jsonString);

  // Deserialization
  Map<String, dynamic> json = jsonDecode(jsonString);
  User deserializedUser = User.fromJson(json);
  print(deserializedUser.name);
  print(deserializedUser.address.street);
}

In the above example, we have a nested Address object within the User class. By properly defining the Address class and using the generated serialization code, we can seamlessly serialize and deserialize the nested object.

Also Read: 40 Useful Flutter extension methods that you never knew

Exploring Easy Ways to Serialize Dart Objects

In addition to Dart’s built-in JSON serialization support, there are third-party libraries available that simplify the serialization process further.
One such library is built_value. It provides a declarative approach to serialization and allows you to define immutable data models using a fluent API. The library generates serialization code based on these definitions, reducing the manual effort required.

To use built_value, follow these steps:

Step 1: Add the built_value and built_value_generator packages to your pubspec.yaml file:

dependencies:
  flutter:
    sdk: flutter
  built_value: ^8.0.0
  built_value_generator: ^8.0.0

dev_dependencies:
  build_runner: ^2.0.0

Step 2: Run flutter pub get to fetch the packages.

Step 3: Define your data model using the built_value API:

import 'package:built_value/built_value.dart';
import 'package:built_value/serializer.dart';

part 'user.g.dart';

abstract class User implements Built<User, UserBuilder> {
  int get id;
  String get name;
  String get email;

  User._();

  factory User([void Function(UserBuilder) updates]) = _$User;

  static Serializer<User> get serializer => _$userSerializer;
}

Step 4: Generate serialization code by running the following command in your terminal:

flutter pub run build_runner build

Step 5: Utilize the generated serialization code in your Flutter project:

import 'package:built_value/standard_json_plugin.dart';
import 'package:built_value/json_object.dart';

void main() {
  // Serialization
  User user = User((b) => b
    ..id = 1
    ..name = 'John Doe'
    ..email = 'john.doe@example.com'
  );
  
  final serializers = (Serializers().toBuilder()
    ..addPlugin(StandardJsonPlugin())
  ).build();
  
  final jsonString = json.encode(serializers.serialize(user));
  print(jsonString);
  
  // Deserialization
  final json = json.decode(jsonString);
  final deserializedUser = serializers.deserialize(json, specifiedType: FullType(User));
  print(deserializedUser.name);
}

In the above example, we defined the User data model using the built_value library. We used the generated serialization code and the StandardJsonPlugin to serialize and deserialize the User object.

Conclusion

In this comprehensive guide, we have explored the world of Flutter Dart serialization, empowering you to efficiently manage data in your Flutter projects. By leveraging Dart’s built-in JSON serialization support or utilizing third-party libraries like json_serializable and built_value, you can streamline the serialization process and focus on building amazing Flutter apps.

Serialization is a fundamental aspect of app development, enabling efficient storage, transmission, and retrieval of data. With Flutter Dart serialization, you can seamlessly convert objects into a structured format, making it easy to store, send over a network, or share across platforms.

By mastering Flutter Dart serialization, you gain the ability to efficiently manage data in your app, enhancing its performance, scalability, and interoperability. Whether you choose to use Dart’s native JSON serialization, leverage third-party packages, or explore advanced concepts like nested objects and complex data structures, serialization opens up a world of possibilities for creating robust and dynamic user experiences.

So, dive into the world of Flutter Dart serialization, unleash your creativity, and unlock the full potential of data management in your Flutter apps. With the knowledge and examples provided in this guide, you are well-equipped to serialize and deserialize data effortlessly, making your app development journey a seamless and enjoyable experience.

Remember to practice and experiment with serialization in your own Flutter projects, utilizing the example codes and techniques discussed. This hands-on experience will solidify your understanding and allow you to apply serialization in real-world scenarios.

By embracing Flutter Dart serialization, you join a vibrant community of developers who are revolutionizing app development with efficient data management. So, start your serialization journey today and build remarkable Flutter apps that deliver exceptional user experiences.

. So What do you think about Flutter Dart Serialization?

Additional resources for Flutter Dart Serialization:

Write A Comment