Flutter Freezed | Models, copyWith, JSON Serialization, Generics & Union Types
Make sure to watch json_seriliazble first.
Freezed class
address.dart
{
"success": true,
"data": {
"street": "123 Main Street",
"district": "Dhaka",
"country": "Bangladesh"
},
"message": "Address fetched"
}
import 'package:freezed_annotation/freezed_annotation.dart';
part 'address.freezed.dart';
part 'address.g.dart';
@freezed
abstract class Address with _$Address {
const factory Address({
required String street,
required String district,
required String country,
}) = _Address;
factory Address.fromJson(Map<String, Object?> json) =>
_$AddressFromJson(json);
static const Address present = Address(
street: "present",
district: "addr.dis",
country: "BD",
);
static const Address permanent = Address(
street: "permanent",
district: "addr.dis",
country: "...",
);
}
person.dart
{
"success": true,
"data": {
"name": "John Doe",
"age": 25,
"address": "Earth",
"skills": ["Dart", "Flutter"],
"presentAddress": {
"street": "123 Main Street",
"district": "Dhaka",
"country": "Bangladesh"
},
"permanentAddress": {
"street": "45 Lake Road",
"district": "Chattogram",
"country": "Bangladesh"
}
},
"message": "Person fetched"
}
import 'package:freezed_annotation/freezed_annotation.dart';
import 'address.dart';
part 'user.freezed.dart';
part 'user.g.dart';
@freezed
abstract class Person with _$Person {
const factory Person({
required String name,
int? age,
@Default("Eath") String? address,
@Default([]) List<String> skills,
required Address presentAddress,
Address? permanentAddress,
}) = _Person;
factory Person.fromJson(Map<String, Object?> json) => _$PersonFromJson(json);
static const Person ui = Person(
name: "0",
age: 0,
skills: [],
presentAddress: Address.present,
permanentAddress: Address.permanent,
);
}
Generic
api_response.dart
import 'package:freezed_annotation/freezed_annotation.dart';
part 'api_response.freezed.dart';
part 'api_response.g.dart';
@Freezed(genericArgumentFactories: true)
abstract class ApiResponse<T> with _$ApiResponse<T> {
const factory ApiResponse({
required bool success,
T? data,
String? message,
}) = _ApiResponse<T>;
factory ApiResponse.fromJson(
Map<String, dynamic> json,
T Function(Object?) fromJsonT,
) => _$ApiResponseFromJson(json, fromJsonT);
}
Union
code-snippet
We are using
typeinstead ofruntimetype
code
import 'package:freezed_annotation/freezed_annotation.dart';
part 'response.freezed.dart';
part 'response.g.dart';
@Freezed(genericArgumentFactories: true, unionKey: "type")
sealed class Response<T> with _$Response<T> {
const factory Response.data(T value) = ResponseData<T>;
const factory Response.error(Object error) = ResponseError<T>;
factory Response.fromJson(
Map<String, dynamic> json,
T Function(Object?) fromJsonT,
) => _$ResponseFromJson(json, fromJsonT);
}
sample json
final jsonUnionPerson = {
"type": "error",
"value": {
"name": "John Doe",
"age": 25,
"address": "Earth",
"skills": ["Dart", "Flutter"],
"presentAddress": {
"street": "123 Main Street",
"district": "Dhaka",
"country": "Bangladesh",
},
"permanentAddress": {
"street": "45 Lake Road",
"district": "Chattogram",
"country": "Bangladesh",
},
},
};
final jsonUnionAddress = {
"type": "error",
"value": {
"street": "123 Main Street",
"district": "Dhaka",
"country": "Bangladesh",
},
};
final personErrorJson = {
"type": "error",
"error": "Person not found",
};