google / google/json_serializable.dart
Allow extension type as Map keys if it extends one of primitive json types or has toJson() method
- Dominant language
- Dart
- Stars
- 1.6k
- Forks
- 461
- Avg merge
- 45m
- Merged PRs (30d)
- 1
Description
Codegenerator logs error:
> Could not generate `fromJson` code for `map` because of type `ItemId`.
> Map keys must be one of: Object, dynamic, enum, String, BigInt, DateTime, int, Uri.
```dart
@JsonSerializable(explicitToJson: true)
class Item {
Item({required this.id, required this.map});
final ItemId id;
// Problem here
final Map map;
factory Item.fromJson(Map json) => _$ItemFromJson(json);
Map toJson() => _$ItemToJson(this);
}
extension type const ItemId(String id) {
factory ItemId.fromJson(String id) {
// Here could be some logic to parse the id
return ItemId(id);
}
String toJson() {
// Here could be some logic to convert the id to a string
return id;
}
}
```
Expected generated code
```dart
Item _$ItemFromJson(Map json) => Item(
id: ItemId.fromJson(json['id'] as String),
map: (json['map'] as Map).map(
(k, e) => MapEntry(ItemId.fromJson(k as String), ItemId.fromJson(e as String)),
),
);
Map _$ItemToJson(Item instance) => {
'id': instance.id.toJson(),
'map': instance.map.map((k, e) => MapEntry(k.toJson(), e.toJson())),
};
```
Also, the case with `explicitToJson: false` could be tricky because in the `ItemId` class, `toJson` is just an extension method, and `jsonEncode` will simply unbox the `String id` value. This behavior is unexpected if the extension type has a `toJson` method.
Contributor guide
Assessment
This issue has not been assessed yet.