google / json_serializable.dart

Generates utilities to aid in serializing to/from JSON.
https://pub.dev/packages/json_serializable
BSD 3-Clause "New" or "Revised" License
1.55k stars 397 forks source link

Possible bug relating to unused getters #1073

Open andye2004 opened 2 years ago

andye2004 commented 2 years ago
$ flutter --version
Flutter 2.8.0 • channel stable • https://github.com/flutter/flutter.git
Framework • revision cf44000065 (9 days ago) • 2021-12-08 14:06:50 -0800
Engine • revision 40a99c5951
Tools • Dart 2.15.0

This is similar to issue #918 in that it is using extension of a base class, but is actually quite different. I have a situation where I have a base class (a business layer entity) which I am extending in the network layer in order to deserialise the server supplied JSON. The names of the properties in the server-side JSON is pretty verbose and I want to use shorter names in the business entity layer, I therefore need to find a way to tell json_deserialize to map the verbosely named json property into the entity property name.

Given the following:-

class Base {
  final int name;

  Base({required this.name});
}

@JsonSerializable()
class BaseModel extends Base {
  BaseModel({required int reallyVeryVerboseName}) :
        super(name: reallyVeryVerboseName);

  int get reallyVeryVerboseName => name;

  @override
  @JsonKey(ignore: true)
  int get name;

  factory BaseModel.fromJson(Map<String, dynamic> json) =>
      _$BaseModelFromJson(json);

}

it works flawlessly, e.g. I need to supply a getter for the verbose name and override the getter for the simple name and the following code is generated:-

BaseModel _$BaseModelFromJson(Map<String, dynamic> json) => BaseModel(
      reallyVeryVerboseName: json['reallyVeryVerboseName'] as int,
    );

Map<String, dynamic> _$BaseModelToJson(BaseModel instance) => <String, dynamic>{
      'reallyVeryVerboseName': instance.reallyVeryVerboseName,
    };

However, I don't need to serialise the BaseModel therefore added createToJson: false and expected to be able to remove the two getter methods, e.g.

class Base {
  final int name;

  Base({required this.name});
}

@JsonSerializable(createToJson: false)
class BaseModel extends Base {
  BaseModel({required int reallyVeryVerboseName}) :
        super(name: reallyVeryVerboseName);

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

but when I do this I get the following exception:-

[SEVERE] json_serializable:json_serializable on lib/models.dart:

Cannot populate the required constructor argument: reallyVeryVerboseName.
package:test/models.dart:159:3
    ╷
9   │   BaseModel({required int reallyVeryVerboseName}) :
    │   ^
    ╵

Leaving the two getter methods in place and adding createToJson: false, generates the following:-

BaseModel _$BaseModelFromJson(Map<String, dynamic> json) => BaseModel(
      reallyVeryVerboseName: json['reallyVeryVerboseName'] as int,
    );

So it seems that even when setting createToJson: false the getters are still required even though they are not used in the generated code.

So, Is this a bug? Or am I missing something fundamental?

I'm really very new to dart/flutter - I've only been looking for about a week so it may well just be lack of knowledge / understanding on my part.

Johannes5000 commented 1 year ago

Any news about this one?