json_serializable.dart icon indicating copy to clipboard operation
json_serializable.dart copied to clipboard

Feature request: support storing the unused values while decoding in a special field

Open lukepighetti opened this issue 6 years ago • 8 comments

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?

lukepighetti avatar Feb 22 '19 21:02 lukepighetti

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)));
}

lukepighetti avatar Feb 22 '19 21:02 lukepighetti

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.

kevmoo avatar Feb 24 '19 23:02 kevmoo

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)

lukepighetti avatar Feb 25 '19 01:02 lukepighetti

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)));
}

lukepighetti avatar Feb 25 '19 01:02 lukepighetti

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.

kevmoo avatar Feb 25 '19 07:02 kevmoo

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 avatar Feb 25 '19 13:02 lukepighetti

@lukepighetti

Another question: would you want the extra things dumped back out in toJson?

kevmoo avatar May 11 '19 02:05 kevmoo

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.

lukepighetti avatar Jun 10 '19 14:06 lukepighetti