json_serializable.dart
json_serializable.dart copied to clipboard
When generating a List, the list type is invalid
Versions:
Dart SDK version: 3.3.0 (stable) (Tue Feb 13 10:25:19 2024 +0000) on "windows_x64"
Flutter 3.19.1 • channel stable • https://github.com/flutter/flutter.git Framework • revision abb292a07e (6 days ago) • 2024-02-20 14:35:05 -0800 Engine • revision 04817c99c9 Tools • Dart 3.3.0 • DevTools 2.31.1
I have a problem when I generate file using annotations @JsonSerializable and @RealmModel, the generator no set te correct type of list.
I have these classes:
@RealmModel()
@JsonSerializable()
class $EmpresaFilial {
late $Empresa? empresa;
late List<$Filial> filiais;
EmpresaFilial toRealmObject() {
return EmpresaFilial(
empresa: empresa!.toRealmObject(),
filiais: filiais.map((f) => f.toRealmObject()).toList(),
);
}
static fromJson(Map<String, dynamic> json) => _$$EmpresaFilialFromJson(json);
Map<String, dynamic> toJson() => _$$EmpresaFilialToJson(this);
}
extension EmpresaFilialJsonHandler on EmpresaFilial {
static EmpresaFilial fromJson(Map<String, dynamic> json) =>
_$$EmpresaFilialFromJson(json).toRealmObject();
Map<String, dynamic> toJson() => _$$EmpresaFilialToJson(this);
}
@RealmModel()
@JsonSerializable()
class $Filial {
@PrimaryKey()
late int? id;
late String? nome;
Filial toRealmObject() {
return Filial(
id,
nome: nome,
);
}
static fromJson(Map<String, dynamic> json) => _$$FilialFromJson(json);
Map<String, dynamic> toJson() => _$$FilialToJson(this);
}
extension FilialJsonHandler on Filial {
static Filial fromJson(Map<String, dynamic> json) =>
_$$FilialFromJson(json).toRealmObject();
Map<String, dynamic> toJson() => _$$FilialToJson(this);
}
And this is a json_serializable
generated code:
$EmpresaFilial _$$EmpresaFilialFromJson(Map<String, dynamic> json) =>
$EmpresaFilial()
..empresa = json['empresa'] == null
? null
: $Empresa.fromJson(json['empresa'] as Map<String, dynamic>)
..filiais = (json['filiais'] as List<dynamic>)
.map((e) => $Filial.fromJson(e as Map<String, dynamic>))
.toList(); <== HERE IS THE PROBLEM
Map<String, dynamic> _$$EmpresaFilialToJson($EmpresaFilial instance) =>
<String, dynamic>{
'empresa': instance.empresa,
'filiais': instance.filiais,
};
When returning from the fromJson method of the generated code, I receive this error
A value of type 'List<dynamic>' can't be assigned to a variable of type 'List<$Filial>'.
Try changing the type of the variable, or casting the right-hand type to 'List<$Filial>'.
I managed to adjust by placing a cast for List<$Filial>
in the file generated at the end of the method, but this is unfeasible, since when the file is generated again, this manual cast will be deleted
Yeah, i had the same problem. When it try to convert List
MangaModel._categoryFromJson(json['genres'] as List<String>)
Error message:
type 'List
I manually must change to: MangaModel._categoryFromJson(List<String>.from(json['genres']))
Please provide a minimal reproduction without all of the extra extension types, static helpers, etc.
I tried to create something minimal and it looks fine
@JsonSerializable()
class EmpresaFilial {
final List<Filial> filiais;
EmpresaFilial({required this.filiais});
factory EmpresaFilial.fromJson(Map<String, dynamic> json) =>
_$EmpresaFilialFromJson(json);
Map<String, dynamic> toJson() => _$EmpresaFilialToJson(this);
}
@JsonSerializable()
class Filial {
final int? id;
final String? nome;
Filial(this.id, {this.nome});
factory Filial.fromJson(Map<String, dynamic> json) => _$FilialFromJson(json);
Map<String, dynamic> toJson() => _$FilialToJson(this);
}
EmpresaFilial _$EmpresaFilialFromJson(Map<String, dynamic> json) =>
EmpresaFilial(
filiais: (json['filiais'] as List<dynamic>)
.map((e) => Filial.fromJson(e as Map<String, dynamic>))
.toList(),
);
Map<String, dynamic> _$EmpresaFilialToJson(EmpresaFilial instance) =>
<String, dynamic>{
'filiais': instance.filiais,
};
Filial _$FilialFromJson(Map<String, dynamic> json) => Filial(
json['id'] as int?,
nome: json['nome'] as String?,
);
Map<String, dynamic> _$FilialToJson(Filial instance) => <String, dynamic>{
'id': instance.id,
'nome': instance.nome,
};
@JsonSerializable()
class MangaModel {
@JsonKey(name: 'id')
final String id;
@JsonKey(name: 'name')
final String title;
@JsonKey(name: 'genres', toJson: _categoryToJson, fromJson: _categoryFromJson)
final List<CategoryModel> categories;
const MangaModel({
required this.id,
required this.title,
required this.categories,
});
factory MangaModel.fromJson(JsonMap json) {
return _$MangaModelFromJson(json);
}
JsonMap toJson() {
return _$MangaModelToJson(this);
}
static List<CategoryModel> _categoryFromJson(List<String> list) {
final genres =
list.map((category) => CategoryModel.findByApiName(category)).toList();
return genres;
}
static List<String> _categoryToJson(List<CategoryModel> categories) {
final genres = categories.map((e) => e.apiName).toList();
return genres;
}
}
enum CategoryModel {
none('', ''),
isekai('Isekai', 'Isekai'),
fantasy('Fantasy', 'Fantasy'),
action('Action', 'Action'),
harem('Harem', 'Harem'),
shounen('Shounen', 'Shounen'),
scify('Sci-fy', 'Sci-y'),
horror('Horror', 'Horror');
final String appName;
final String apiName;
const CategoryModel(this.appName, this.apiName);
static CategoryModel findByApiName(String name) {
return CategoryModel.values.firstWhere(
(element) => element.apiName == name,
orElse: () => CategoryModel.none,
);
}
}
MangaModel _$MangaModelFromJson(Map<String, dynamic> json) => MangaModel(
id: json['id'] as String,
title: json['name'] as String,
//This code returns: type 'List' is not a subtype of type 'List' in type cast
categories: MangaModel._categoryFromJson(json['genres'] as List<String>),
//I need to change to:
//categories: MangaModel._categoryFromJson(List.from(json['genres'])),
);
Map<String, dynamic> _$MangaModelToJson(MangaModel instance) =>
<String, dynamic>{
'id': instance.id,
'name': instance.title,
'genres': MangaModel._categoryToJson(instance.categories),
};
Ah! You need to update _categoryFromJson
to take List<dynamic>
and do the conversion there! the fromJson:
param in JsonKey
is exactly that! You need to make the type JSON-compatible!