google / json_serializable.dart

Generates utilities to aid in serializing to/from JSON.
https://pub.dev/packages/json_serializable
BSD 3-Clause "New" or "Revised" License
1.55k stars 397 forks source link

support for nested items in @JsonKey(name:) #490

Closed KorbinianMossandl closed 2 years ago

KorbinianMossandl commented 5 years ago

It would be great if we could directly access nested items in the name String of @JsonKey. Consider this Json:

"root_item": {
    "items": [
        {
            "name": "first nested item"
        },
        {
            "name": "second nested item"
        }
    ]
}

I would like to do:

@JsonKey(name: "root_item/items")
List<NestedItem> nestedItems;

Sorry if this is already possible, but i could not find anything.

kevmoo commented 5 years ago

Interesting idea. It is currently not supported.

vanlooverenkoen commented 5 years ago

This should really be added. Now we have to create extra objects because we had to use a crappy backend. Using a simple api to flatten your backend models

jayden320 commented 5 years ago

I really need this feature. Is it supported now?

vanlooverenkoen commented 5 years ago

Is there a roadmap for this feature? What timeframe could we expect for a P2?

k-paxian commented 4 years ago

If you guys are still waiting for that feature, this library already has it implemented https://github.com/k-paxian/dart-json-mapper#nesting-configuration

@KorbinianMossandl thank you for a great idea! This thing is called rfc6901

vanlooverenkoen commented 4 years ago

Thanks. but I need to use json_serializable. Because I am using retrofit.dart that uses toJson and fromJson.

kevmoo commented 4 years ago

PRs welcome here!

NicolaVerbeeck commented 4 years ago

I am working on an implementation for this. Rough draft can be found here: https://github.com/Chimerapps/json_serializable/tree/feature/json_path

WIP, not ready for production

mokai commented 4 years ago

Necessary function !

taoyimin commented 4 years ago

I really need this feature!

masewo commented 4 years ago

I forked @NicolaChimerapps fork and corrected two small errors: https://github.com/masewo/json_serializable/tree/feature/json_path For now it is working for me.

kevmoo commented 4 years ago

@masewo and @NicolaChimerapps – I'll happily take a solid PR with testing, etc

ouyanghuacom commented 4 years ago

It's wishful for me.

jeffaknine commented 4 years ago

Any update on this ?

miguelpruivo commented 4 years ago

Bumping as this is a must have.

kevmoo commented 4 years ago

Pull requests welcome – beyond the core features offered now, this package is a "beyond work hours" project.

hacker1024 commented 3 years ago

If #783 gets merged, this will be possible, albeit in a convoluted manner:

@JsonSerializable()
class MyObject {
  @JsonKey(name: 'myRegularField')
  final String myRegularField;

  @JsonKey(extra: true)
  final String myNestedField;

  MyObject({
    required this.myRegularField,
    required this.myNestedField,
  });

  factory MyObject.fromJson(Map<String, dynamic> json) {
    return _$MyObjectFromJson(
      json,
      myNestedField: json['myInnerObject']['myNestedField'] as String,
    );
  }

  Map<String, dynamic> toJson() {
    final output = _$MyObjectToJson(this);
    output['myInnerObject'] = {'myNestedField': myNestedField};
    return output;
  }
}
NicolaVerbeeck commented 3 years ago

How does 368a8c7 fix this?

kevmoo commented 3 years ago

gah! Wrong issue!

ciriousjoker commented 2 years ago

Any news on this? It's marked as help wanted and there's an open PR related to it :/

kevmoo commented 2 years ago

There is NOT an open PR on this. That was a mistake.

The issue here: we need some other syntax for key that's not a String because any String can be a valid key in a JSON map. So we'd need to support List<String> for key – or add another value. Both of which are quite a bit of work!

ad-on-is commented 2 years ago

There is NOT an open PR on this. That was a mistake.

The issue here: we need some other syntax for key that's not a String because any String can be a valid key in a JSON map. So we'd need to support List<String> for key – or add another value. Both of which are quite a bit of work!

How about something like

@JsonSerialiable(explicitJson: true, keySeparator: ">")

class Person {
@JsonKey(name: 'name>fist_name')
String name;
}
kevmoo commented 2 years ago

After consideration, I've decided not to invest time here. It adds a LOT of complexity.

If you still want this feature, it's pretty easy to implement with a JsonConverter

See https://github.com/google/json_serializable.dart/blob/master/example/lib/nested_values_example.dart

qevka commented 2 years ago

After consideration, I've decided not to invest time here. It adds a LOT of complexity.

If you still want this feature, it's pretty easy to implement with a JsonConverter

See https://github.com/google/json_serializable.dart/blob/master/example/lib/nested_values_example.dart

That would be nice if JsonConvert was actually working. I am having the same problem that is mentioned here: https://github.com/google/json_serializable.dart/issues/1066

I tried downgrading my build_runner and json_annotation packages and also tried just using your code directly neither worked.

Alameen688 commented 2 years ago

In my case I didn't need the toJson data to transform data back to the original structure I just needed to read the correct data and readValue worked perfectly fine in combination with deep_pick.

@JsonKey(readValue: readNestedItems)
List<NestedItem> nestedItems;
  static List<String, dynamic> readNestedItems(Map json, String key) {
    final fields = pick(json, key, 'items').asListOrEmpty(_yourFromPickFunction);
    return fields;
  }
Veeksi commented 2 years ago

After consideration, I've decided not to invest time here. It adds a LOT of complexity. If you still want this feature, it's pretty easy to implement with a JsonConverter See https://github.com/google/json_serializable.dart/blob/master/example/lib/nested_values_example.dart

That would be nice if JsonConvert was actually working. I am having the same problem that is mentioned here: #1066

I tried downgrading my build_runner and json_annotation packages and also tried just using your code directly neither worked.

I am also having this exact same problem with the explicit json converter

JPaulMora commented 1 year ago

Chiming in to show support/need for this functionality.

rignaneseleo commented 11 months ago

Up

EvGeniyLell commented 10 months ago

I'm use next solution

@JsonKey(readValue: nestedReader, name: 'extras/apiKey') List<String>? extras,

where nestedReader is

Object? nestedReader(Map json, String key) {
  final keys = key.split('/');
  return _nestedReader(json, keys);
}

Object? _nestedReader(final Object? object, Iterable<String> keys) {
  if (keys.isEmpty || object == null) {
    return object;
  }
  if (object is Map) {
    final subObject = object[keys.first];
    final subKeys = keys.skip(1);
    return _nestedReader(subObject, subKeys);
  }
  if (object is List) {
    return object.fold<dynamic>([], (list, subObject) {
      return list..add(_nestedReader(subObject, keys));
    });
  }
  return object;
}

for this test

void main() {
  final Map map = {
    'extras': [
      {'apiKey': 1, 'name': 'a'},
      {'apiKey': 3, 'name': 'b'},
      {'apiKey': 5, 'name': 'c'},
      {'apiKey': 7, 'name': 'd'},
    ]
  };

  final result = nestedReader(map, 'extra/apiKey');
  print('result $result');
}

result will be

result (1, 3, 5, 7)


update: also we can declare

class NestedJsonKey extends JsonKey {
  const NestedJsonKey({
    required super.name,
  }) : super(readValue: nestedReader);
}

and use it as

@NestedJsonKey(name: 'lastLocation/lng') double? test,
devnta commented 7 months ago

There is no solution to this problem in 2024

creativecreatorormaybenot commented 7 months ago

@phamquoctrongnta check https://github.com/google/json_serializable.dart/commit/2dfffd0df2abc4592b37e75de2ee75932711c503.