Module 2
Topic 4

Serialization

Converting between JSON and Dart objects — from manual serialization to the json_serializable package.

json_serializable Flutter Docs – JSON
What Is Serialization?

Serialization is the process of converting Dart objects to JSON strings (and vice versa). It's essential for:

  • Sending data to an API (POST/PUT requests)
  • Receiving data from an API (GET responses)
  • Saving data to local storage
  • Passing data between screens

🎯 Two Directions

  • Deserialization – JSON → Dart object ( fromJson )
  • Serialization – Dart object → JSON ( toJson )

There are two main approaches to serialization in Flutter:

  • Manual Serialization – Writing fromJson and toJson methods by hand
  • Code Generation – Using json_serializable to auto-generate the code
Manual Serialization

Manual serialization involves writing fromJson and toJson methods yourself. It's simple but becomes tedious for large models.

✅ Pros & Cons

  • Pros: Simple, no dependencies, full control
  • Cons: Boilerplate-heavy, error-prone for large models
  • Best for: Small projects or simple models
json_serializable Package

json_serializable is the recommended approach for production apps. It uses code generation to automatically create fromJson and toJson methods.

🎯 Why json_serializable?

  • Type-safe – Catches errors at compile time
  • Less boilerplate – Write only the model fields
  • Handles nested objects – Works with nested models
  • Configurable – Supports custom field names
  • Null safety – Full support for null-safe Dart
Setting Up json_serializable

To use json_serializable , you need to add several dependencies and run a build command.

Step 1
Add dependencies to pubspec.yaml
Step 2
Create a model class with annotations
Step 3
Run dart run build_runner build
Using json_serializable

Here's how to define a model class with json_serializable annotations.

Step-by-Step Explanation
1.
Add Dependencies – Add json_annotation , json_serializable , and build_runner to your pubspec.yaml .
2.
Create the Model – Define your model class with @JsonSerializable() annotation. Use @JsonKey(name: '...') for custom field names.
3.
Add Part Directive – Add part 'filename.g.dart'; at the top of your file.
4.
Write fromJson/toJson – Call the generated functions: factory User.fromJson(...) => _$UserFromJson(...);
5.
Run Code Generation – Execute dart run build_runner build to generate the .g.dart files.
Complete Example: Users App

Here's a complete example using json_serializable with a nested model.

Manual vs Code Generation

Manual Serialization

  • No dependencies needed
  • Full control over parsing
  • Simple to understand
  • Becomes tedious for large models
  • Error-prone when fields change
  • No compile-time validation

json_serializable

  • Requires additional dependencies
  • Auto-generates boilerplate code
  • Type-safe at compile time
  • Handles nested objects automatically
  • Easy to update when fields change
  • Recommended for production apps

💡 Recommendation

Use json_serializable for all production apps. The initial setup takes a few minutes, but it saves hours of writing boilerplate and prevents bugs. Manual serialization is fine for small projects or simple models with 1-2 fields.

Common Mistakes
❌ Mistake 1: Forgetting to run build_runner

After adding or changing annotations, you must run dart run build_runner build to regenerate the .g.dart files.

✅ Correct: Run build_runner after changes

Use dart run build_runner watch to auto-generate files when you save changes.

❌ Mistake 2: Forgetting the part directive

Without part 'filename.g.dart'; , the generated code won't be accessible.

✅ Correct: Always add part directive

Add part 'filename.g.dart'; at the top of your file after the imports.

❌ Mistake 3: Not handling nested objects

If your model contains nested objects, you need explicitToJson: true and the nested objects must also have toJson methods.

✅ Correct: Use explicitToJson for nested objects

Add @JsonSerializable(explicitToJson: true) to the parent model.

🎯 Key Takeaway

JSON serialization is essential for API communication. json_serializable is the recommended approach for production Flutter apps — it's type-safe, reduces boilerplate, and handles complex nested objects. Always run build_runner after making changes.