google / google/json_serializable.dart

Allow extension type as Map keys if it extends one of primitive json types or has toJson() method

Open
#1,406 2 comments 21 reactions 0 assignees View on GitHub
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.