Reputation: 215
I have a generic data model in Flutter using the JsonSerializable. I want to pass a custom parameter name (e.g., "statistics") instead of a fixed name in the fromJson and toJson methods. Here's my current implementation:
import 'package:json_annotation/json_annotation.dart';
part 'data_model.g.dart';
@JsonSerializable(genericArgumentFactories: true)
class DataModel<T, P> {
final int? total;
final List<T> items;
final P? param;
DataModel({
this.total,
required this.items,
this.param,
});
factory DataModel.fromJson(
Map<String, dynamic> json,
T Function(Object?) fromJsonT,
P Function(Object?) fromJsonP,
) {
final List<dynamic> itemsJson = json['items'] as List<dynamic>;
final List<T> items = itemsJson
.map<T>((item) => fromJsonT(item as Map<String, dynamic>))
.toList();
final dynamic paramJson = json['statistics'] as dynamic; // <- pass the param name instead of 'statistics'
final P? pamPam = fromJsonP(paramJson);
return DataModel<T, P>(
total: (json['total'] != null && json['total'] is int)
? json['total'] as int
: null,
param: pamPam,
items: items,
);
}
Map<String, dynamic> toJson(Object? Function(T) toJsonT, Object? Function(P) toJsonP) {
final List<dynamic> itemsJson =
items.map<dynamic>((item) => toJsonT(item)).toList();
return {
'total': total,
'statistics': toJsonP, // <- pass the param name instead of 'statistics'
'items': itemsJson,
};
}
}
Here is JSON example how it works now:
{
"total":2,
"items":[
{
"id":1,
"name":"John"
},
{
"id":2,
"name":"Max"
}
],
"statistics":{
"views":50,
"downloads":100
}
}
My objective is to make field statistics more generic. The aim is to establish a logic wherein an alternative object can be passed as a generic parameter alongside the respective JSON key name. For instance, "other" could be passed instead of "statistics." Example:
{
"total":2,
"items":[
{
"id":1,
"name":"John"
},
{
"id":2,
"name":"Max"
}
],
"other":{
"invites":50
}
}
Maybe we can create one more parameter like 'N' name and parse it in fromJson and toJson methods. Or maybe it is not possible at all.
Upvotes: 0
Views: 49
Reputation: 512
You can turn the field name in a parameter/property, and keep 'statistics'
as a default.
import 'package:json_annotation/json_annotation.dart';
part 'data_model.g.dart';
@JsonSerializable(genericArgumentFactories: true)
class DataModel<T, P> {
final int? total;
final List<T> items;
final P? param;
final String paramName;
DataModel({
this.total,
required this.items,
this.param,
required this.paramName,
});
factory DataModel.fromJson(
Map<String, dynamic> json,
T Function(Object?) fromJsonT,
P Function(Object?) fromJsonP,
{String paramName = 'statistics'}
) {
final List<dynamic> itemsJson = json['items'] as List<dynamic>;
final List<T> items = itemsJson
.map<T>((item) => fromJsonT(item as Map<String, dynamic>))
.toList();
final dynamic paramJson = json[paramName] as dynamic;
final P? pamPam = fromJsonP(paramJson);
return DataModel<T, P>(
total: (json['total'] != null && json['total'] is int)
? json['total'] as int
: null,
param: pamPam,
items: items,
paramName: paramName,
);
}
Map<String, dynamic> toJson(Object? Function(T) toJsonT, Object? Function(P) toJsonP) {
final List<dynamic> itemsJson =
items.map<dynamic>((item) => toJsonT(item)).toList();
return {
'total': total,
paramName: toJsonP,
'items': itemsJson,
};
}
}
(By the way, JsonSerializable
is not really used here, you are just parsing and formatting it without using its generated code. Are you sure you need it?)
Upvotes: 1