json_serializable.dart
json_serializable.dart copied to clipboard
Feature request: support storing the unused values while decoding in a special field
I have a situation where the fields of a map are always changing and I need to expose some metadata that is consistent but also the data fields.
Looking for something like this:
@JsonSerializable(createToJson: false)
class Entry {
final Meta meta;
@JsonKey(restJson: true)
final Map<String, dynamic> data;
Entry(this.meta, this.data);
factory Entry.fromJson(Map json) => _$EntryFromJson(json);
}
The idea is that the entire json map would be stored at Entry.data and would be packaged up with all of its metadata.
Is there any way to achieve this today?
My modified generated code looks like this
// GENERATED CODE - DO NOT MODIFY BY HAND 😂
part of 'entry.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
Entry _$EntryFromJson(Map json) {
return Entry(
json['__meta__'] == null ? null : Meta.fromJson(json['__meta__'] as Map),
json['id'] as int,
(json)?.map((k, e) => MapEntry(k as String, e)));
}
Oh, so you want the ability to store the json content as well as the fields?
I doubt I'll do that work, but I'd accept a pull request.
I started poking around the repo but didn't get very far. Any suggestions for strategy? I was thinking of just adding a bool restData argument to @JsonKey() The goal would be to store everything that wasn't explicitly specified as a field. The problem is what to do if someone specifies two different keys as restData (perhaps its not actually a problem)
Also, here is a more accurate representation of what I'd like to generate
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'entry.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
Entry _$EntryFromJson(Map json) {
return Entry(
json['__meta__'] == null ? null : Meta.fromJson(json['__meta__'] as Map),
json['id'] as int,
((json ?? {})..removeWhere((k, e) => k == "__meta__" || k == "id"))
.map((k, e) => MapEntry(k as String, e)));
}
Instead of removeWhere you likely want Map.fromEntries(json.entries.where((e) => const !['__meta__', 'id'].contains(e) or something.
I'd also suggest adding a different annotation all together. Something like JsonRest – since the other values on JsonKey would be noise.
Sounds like a new annotation like @JsonRest({bool trimmed = true}) (or maybe bool all = false ?) would be appropriate. I'll put a couple hours into this later and see how far I get.
@lukepighetti
Another question: would you want the extra things dumped back out in toJson?
Hi @kevmoo, I've been away from GitHub the last couple months. I don't personally have a need for that feature, and this issue / feature request is not a blocker for me at the moment.