Search code examples
flutterhivefreezedjson-serializable

Generated class from freezed creates duplicate FromJson method


I have a class which I am trying to use with Freezed, Json Serializable, and Hive. After running dart run build_runner build and generating the necessary classes, my compiler gives me the following error:

: Error: Can't use '_$FooBarFromJson' because it is declared more than once.

and

: Error: '_$FooBarFromJson' is already declared in this scope.

part 'foobar.freezed.dart';
part 'foobar.g.dart';

@freezed
@JsonSerializable(explicitToJson: true)
@HiveType(typeId: 0)
class FooBar extends HiveObject with _$FooBar  {

  factory FooBar({
    @HiveField(0) required int baz
  }) = _FooBar;

  factory FooBar.fromJson(Map<String, dynamic> json) =>
      _$FooBarFromJson(json);
  }
}

After looking through the generated classes, my foobar.g.dart file contains the following methods:

FooBar _$FooBarFromJson(Map<String, dynamic> json) => FooBar(
      baz: json['baz'] as int,
    );

Map<String, dynamic> _$FooBarToJson(FooBar instance) =>
    <String, dynamic>{
      'baz': instance.baz,
    };

_$_FooBar _$$_FooBarFromJson(Map<String, dynamic> json) =>
    _$_FooBar(
      baz: json['baz'] as int,
    );

Map<String, dynamic> _$$_FooBarToJson(_$_FooBar instance) =>
    <String, dynamic>{
      'baz': instance.baz,
    };

And my foobar.freezed.dart contains this method:

FooBar _$FooBarFromJson(Map<String, dynamic> json) {
  return _FooBar.fromJson(json);
}

I've noticed that other files that get converted only have the methods with the _$$_ prefix in foobar.g.dart, whereas _$FooBarFromJson is being created in both foobar.freezed.dart and foobar.g.dart, which is the cause of the errors. What am I missing here?


Solution

  • According to the following this comment in a freezed issue and as shown in the package readme example, you need to place the @JsonSerializable(explicitToJson: true) inside the class in the following manner:

    part 'foobar.freezed.dart';
    part 'foobar.g.dart';
    
    @freezed
    @HiveType(typeId: 0)
    class FooBar extends HiveObject with _$FooBar  {
      @JsonSerializable(explicitToJson: true) // <~~~ here
    
      factory FooBar({
        @HiveField(0) required int baz
      }) = _FooBar;
    
    
      factory FooBar.fromJson(Map<String, dynamic> json) =>
          _$FooBarFromJson(json);
      }
    }
    
    

    You will notice this will give you the following warning:

    The annotation 'JsonSerializable' can only be used on classes
    

    This is a known issue/limitation and the maintainer recommends disabling that specific warning as discussed here.

    I believe an alternative approach is to create build.yaml and specify explicitToJson in there but I don't have much knowledge there.