I have a class called Groups
that has a property that contains a list of Member
s.
To send this to Firebase, I have a GroupDto
and MemberDto
class that converts these values to and from the domain, and to and from JSON.
I noticed a recent issue where every time I try to save a group update, I'm getting this error that says:
ArgumentError (Invalid argument: Instance of 'MemberDto')
It seems to happen as part of the method that converts the GroupDto to Json, when I look at the value that's being mapped, it seems to be storing those as a list of MemberDto instead of a list of mapped values:
I have this list of MemberDtos set to also convert to Json, with explicitToJson equal to true.
Any idea what could be causing this?
Here are my classes for GroupDto and MemberDto:
@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);
}
And here is the auto-generated JsonSerializable 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',
};
To get the list of mapped values from the instance try this example: Try getting the list of mapped values by mapping each instance to json then to list.
Example
An instance of
GroupDto
toJson()
ongroups
, it should return a mapMemberDto
from the maptoJson()
method, then return them as list withtoList()
That should give you a map of
MembersDto
Edit
The problem is with the nested
List<MemberDto>?
object.If you want the the package to do it for you, Change the
explicitToJson
option of theJsonSerializable
annotation in the parent class totrue
.Thanks to this answer for pointing it out.