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

Json_serializable not converting ExplicitToJson sub-fields properly #1365

Open Quesajo17 opened 11 months ago

Quesajo17 commented 11 months ago

Issue

I'm having an issue with json_serializable, with a class, GroupDto that has a property made up of a List of MemberDto within it.

It is supposed to convert the List of MemberDto to Json as well, but it appears this is not happening - I keep getting the following error: Argument Error: Instance of 'MemberDto'

When I inspect the element as the Json conversion is happening, it appears the list is still being returned as a MemberDto, instead of converting to Json.

This issue was happening on version 6.6.1, but I upgraded to version 6.7.1 and it is still happening.

Note: I also have 2 other classes set up in a similar way, and the issue is present with them as well.

Class Code

import 'package:json_annotation/json_annotation.dart';

part 'group_dto.g.dart';

@JsonSerializable(includeIfNull: false)
class GroupDto {
  @JsonKey(includeFromJson: false, includeToJson: false)
  final String? id;
  final String title;
  final String? description;
  final List<MemberDto>? members;

  GroupDto({
    this.id,
    required this.title,
    this.description,
    this.members,
  });

  factory GroupDto.fromDomain(Group group) {
    return GroupDto(
      id: group.id,
      title: group.title.getOrCrash(),
      description: group.description,
      members: group.members.isNotEmpty
          ? group.members.map((e) => MemberDto.fromDomain(e)).toList()
          : null,
    );
  }

  Group toDomain() {
    return Group(
      id: id,
      title: ItemTitle(title),
      description: description,
      members: members != null
          ? members!.map((dto) => dto.toDomain()).toList()
          : const [],
    );
  }

  factory GroupDto.fromFirestore(
          Map<String, dynamic> json, String documentId) =>
      _$GroupDtoFromJson(json).copyWith(id: documentId);

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

  Map<String, dynamic> toJson() => _$GroupDtoToJson(this);

  GroupDto copyWith({
    String? id,
    String? title,
    String? description,
    List<MemberDto>? members,
  }) {
    return GroupDto(
      id: id ?? this.id,
      title: title ?? this.title,
      description: description ?? this.description,
      members: members ?? this.members,
    );
  }
}

@JsonSerializable(includeIfNull: false, explicitToJson: true)
class MemberDto {
  final String userId;
  final MembershipStatus status;

  MemberDto({
    required this.userId,
    required this.status,
  });

  factory MemberDto.fromDomain(Member membership) {
    return MemberDto(
      userId: membership.userId,
      status: membership.status,
    );
  }

  Member toDomain() {
    return Member(
      userId: userId,
      status: status,
    );
  }

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

  Map<String, dynamic> toJson() => _$MemberDtoToJson(this);
}

Generated Code

// GENERATED CODE - DO NOT MODIFY BY HAND

part of 'group_dto.dart';

// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************

GroupDto _$GroupDtoFromJson(Map<String, dynamic> json) => GroupDto(
      title: json['title'] as String,
      description: json['description'] as String?,
      members: (json['members'] as List<dynamic>?)
          ?.map((e) => MemberDto.fromJson(e as Map<String, dynamic>))
          .toList(),
    );

Map<String, dynamic> _$GroupDtoToJson(GroupDto instance) {
  final val = <String, dynamic>{
    'title': instance.title,
  };

  void writeNotNull(String key, dynamic value) {
    if (value != null) {
      val[key] = value;
    }
  }

  writeNotNull('description', instance.description);
  writeNotNull('members', instance.members);
  return val;
}

MemberDto _$MemberDtoFromJson(Map<String, dynamic> json) => MemberDto(
      userId: json['userId'] as String,
      status: $enumDecode(_$MembershipStatusEnumMap, json['status']),
    );

Map<String, dynamic> _$MemberDtoToJson(MemberDto instance) => <String, dynamic>{
      'userId': instance.userId,
      'status': _$MembershipStatusEnumMap[instance.status]!,
    };

const _$MembershipStatusEnumMap = {
  MembershipStatus.active: 'active',
  MembershipStatus.invited: 'invited',
  MembershipStatus.notYetSent: 'notYetSent',
  MembershipStatus.rejected: 'rejected',
  MembershipStatus.left: 'left',
  MembershipStatus.removed: 'removed',
  MembershipStatus.none: 'none',
};

Flutter Version

Flutter 3.13.8 • channel stable • https://github.com/flutter/flutter.git Framework • revision 6c4930c4ac (11 days ago) • 2023-10-18 10:57:55 -0500 Engine • revision 767d8c75e8 Tools • Dart 3.1.4 • DevTools 2.25.0

MagTuxGit commented 11 months ago

Try adding explicitToJson: true to the GroupDto.