Reputation: 2742
We are trying to create a generic Category class. At the time being, we are unsure whether category will have integer or UUID as key. Hence, we need the id to be generic for now. All works fine. However, we are unable to generate the fromJson() and toJson() using the freezed
package.
import 'package:freezed_annotation/freezed_annotation.dart';
part 'category.freezed.dart';
part 'category.g.dart';
@freezed
@JsonSerializable(genericArgumentFactories: true)
class Category<T> with _$Category<T> {
factory Category({
required T id,
required String name,
required String imageUrl,
}) = _Category;
factory Category.fromJson(Map<String, dynamic> json) =>
_$CategoryFromJson(json);
}
Error:
Could not generate `fromJson` code for `id` because of type `T` (type parameter).
To support type parameters (generic types) you can:
* Use `JsonConverter`
https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonConverter-class.html
* Use `JsonKey` fields `fromJson` and `toJson`
https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonKey/fromJson.html
https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonKey/toJson.html
* Set `JsonSerializable.genericArgumentFactories` to `true`
https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonSerializable/genericArgumentFactories.html
package:mobile/data/models/category.freezed.dart:144:11
╷
144 │ final T id;
│ ^^
╵
[SEVERE] Failed after 2.4s
pub finished with exit code 1
As the error message suggests, I have used the @JsonSerializable(genericArgumentFactories: true)
annotation however, it is not working as suggested. How can I get the fromJson()
and toJson()
methods with freezed for generics?
Upvotes: 5
Views: 4795
Reputation: 7050
Fixed using @JsonSerializable(genericArgumentFactories: true)
As per docs:
When
true
on classes with type parameters (generic types), extra "helper" parameters will be generated forfromJson
and/ortoJson
to support serializing values of those types.For example, the generated code for
@JsonSerializable(genericArgumentFactories: true) class Response<T> { int status; T value; }
Looks like
Response<T> _$ResponseFromJson<T>( Map<String, dynamic> json, T Function(Object json) fromJsonT, ) { return Response<T>() ..status = json['status'] as int ..value = fromJsonT(json['value']); } Map<String, dynamic> _$ResponseToJson<T>( Response<T> instance, Object Function(T value) toJsonT, ) => <String, dynamic>{ 'status': instance.status, 'value': toJsonT(instance.value), };
Notes:
- This option has no effect on classes without type parameters. If used on such a class, a warning is echoed in the build log.
- If this option is set for all classes in a package via
build.yaml
it is only applied to classes with type parameters – so no warning is echoed.
Upvotes: 1
Reputation: 1498
If I'm not mistaken it's already supported: https://pub.dev/packages/freezed#deserializing-generic-classes
The only thing that you would need to adjust in your code is fromJson
function to:
factory Category.fromJson(Map<String, dynamic> json, T Function(Object?) fromJsonT) => _$CategoryFromJson(json, fromJsonT);
Upvotes: 4