google / google/json_serializable.dart
Proposal: Update explicitToJson:false to use still be lazy but return a custom collection instance
- Dominant language
- Dart
- Stars
- 1.6k
- Forks
- 461
- Avg merge
- 45m
- Merged PRs (30d)
- 1
Description
The current behavior of `explicitToJson: false` seems problematic, as the output of `toJson` does not respect the JSON contract – which is allowing only List/Map/num/bool/String
While `dart:convert` supports it, there are alternatives that do not. Meaning that those alternatives will throw exceptions when receiving the output of a json_serializable's toJson. This is confusing to users, as error messages tend to be cryptic. And it ends up with users disabling `explicitToJson` globally, decreasing the value of this feature quite a bit.
## Proposal
Would it be possible to update `explicitToJson` to render valid JSON output, while preserving the laziness of the encoding?
Say we have:
```dart
@JsonSerializable
class Root {
final Child child;
}
@JsonSerializable
class Child {
final String name;
}
```
I was thinking that instead of having:
```dart
Map _$RootToJson(Root value) {
return {'child': value.child};
}
```
we could have:
```dart
Map _$RootToJson(Root value) {
return {'child': value.child.toJson()};
}
Map _$ChildToJson(Child value) {
return LazyJsonMap(() => {'name': value.name});
}
```
Where the source of `LazyJsonMap` is:
```dart
class LazyJsonMap with MapMixin {
LazyJsonMap(this._toJson);
final Map Function() _toJson;
late final Map _map = _toJson();
@override
Object? operator [](Object? key) => _map[key];
@override
void operator []=(String key, Object? value) => _map[key] = value;
@override
void clear() => _map.clear();
@override
Iterable get keys => _map.keys;
@override
Object? remove(Object? key) => _map.remove(key);
}
```
By doing so, the serialization would still be lazy. But at the same time, if passed to encoders other than `dart:convert`, the output of `toJson` will no-longer throw – as `LazyJsonMap` is a valid `Map` instance
Contributor guide
Assessment
This issue has not been assessed yet.