Ariel
Ariel

Reputation: 2742

Unable to generate fromJson() and toJson() for generics using freezed package

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

Answers (3)

Malwinder Singh
Malwinder Singh

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 for fromJson and/or toJson 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:

  1. This option has no effect on classes without type parameters. If used on such a class, a warning is echoed in the build log.
  2. 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

Karzel
Karzel

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

Ariel
Ariel

Reputation: 2742

Unsupported feature at the moment.

Source: Issue #616

Upvotes: 4

Related Questions