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

[Feature Request] Generate `fromJson`, `toJson` from typedef of `Records` types #1327

Open definev opened 1 year ago

definev commented 1 year ago

Since Dart 3.0, we have Records and it similar to define a class contains only data so in my view this code is equalvalent.


typedef RoomPlanBookingInfo = ({
  /// Id of room plan
  RoomPlanEntity roomPlan,

  /// Properties
  List<ServiceBookingInfo> services,
  int numberOfAdults,
  int numberOfChildren,
  int numberOfBaby,
  String? note,
  ({
    String firstName,
    String lastName,
    String email,
    String phoneNumber,
  }) guest,
});

@JsonSerializable()
class RoomPlanBookingInfoClass {
  final RoomPlanEntity roomPlan;
  final List<ServiceBookingInfo> services;
  final int numberOfAdults; 
  final int numberOfChildren;
  final int numberOfBaby;
  final String? note;
  final ({
    String firstName,
    String lastName,
    String email,
    String phoneNumber,
  }) guest;

  RoomPlanBookingInfoClass({
    required this.roomPlan,
    required this.services,
    required this.numberOfAdults,
    required this.numberOfChildren,
    required this.numberOfBaby,
    required this.note,
    required this.guest,
  }); 
}

If we support typedef for Records typedef the code is elegant like this

@JsonSerializable()
typedef RoomPlanBookingInfo = ({
  /// Id of room plan
  RoomPlanEntity roomPlan,

  /// Properties
  List<ServiceBookingInfo> services,
  int numberOfAdults,
  int numberOfChildren,
  int numberOfBaby,
  String? note,
  ({
    String firstName,
    String lastName,
    String email,
    String phoneNumber,
  }) guest,
});

The fromJson/ toJson methods are implemented in RoomPlanBookingInfoCodable from generator sth like

extension RoomPlanBookingInfoCodable on RoomPlanBookingInfo {
   static RoomPlanBookingInfo fromJson(Map<String, dynamic> json) => _$RoomPlanBookingInfoFromJson(json);

   Map<String, dynamic> toJson() => _$RoomPlanBookingInfoToJson(this);
}
BoyleSeo commented 1 year ago

I think supporting extension types on records prop may be appropriate.

BoyleSeo commented 8 months ago

I think supporting extension types on records prop may be appropriate.

I just realized it's not simple to do. convert::jsonEncode function cannot invoke toJson method anyway because extension types are 0 cost wrapper and do not provide v-table to Object reference..

ralph-bergmann commented 5 months ago

I'm wondering if it might be a compromise to implement only fromJson for records instead of not supporting records at all. Most of the time, I only need fromJson.

Reprevise commented 4 months ago

For the record, this is the error that happens when you try and generate from a record typedef:

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

UnimplementedError: (RecordTypeImpl) ({String key, int value})
package:json_serializable/src/utils.dart 221:3                      typeToCode
dart:_internal                                                      ListIterable.join
package:json_serializable/src/utils.dart 213:48                     typeToCode
package:json_serializable/src/type_helpers/json_helper.dart 135:10  JsonHelper.deserialize
package:json_serializable/src/type_helper_ctx.dart 68:29            TypeHelperCtx.deserialize.<fn>
dart:core                                                           Iterable.firstWhere
package:json_serializable/src/type_helper_ctx.dart 88:46            TypeHelperCtx._run
package:json_serializable/src/type_helper_ctx.dart 65:19            TypeHelperCtx.deserialize
package:json_serializable/src/decode_helper.dart 208:10             DecodeHelper._deserializeForField.deserialize
package:json_serializable/src/decode_helper.dart 230:17             DecodeHelper._deserializeForField
package:json_serializable/src/decode_helper.dart 56:9               DecodeHelper.createFactory.deserializeFun
package:json_serializable/src/decode_helper.dart 332:32             _writeConstructorInvocation.<fn>
dart:core                                                           StringBuffer.writeAll
package:json_serializable/src/decode_helper.dart 330:9              _writeConstructorInvocation
package:json_serializable/src/decode_helper.dart 59:18              DecodeHelper.createFactory
package:json_serializable/src/generator_helper.dart 86:28           GeneratorHelper.generate
dart:_internal                                                      WhereIterator.moveNext
package:json_serializable/src/json_part_builder.dart 64:27          _UnifiedGenerator.generate
package:source_gen/src/builder.dart 342:23                          _generate
dart:async                                                          Stream.toList.<fn>
package:source_gen/src/builder.dart 107:9                           _Builder._generateForLibrary
package:source_gen/src/builder.dart 99:5                            _Builder.build