Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

better reviver API for JsonDecoder #29750

Open
skybrian opened this issue May 30, 2017 · 3 comments
Open

better reviver API for JsonDecoder #29750

skybrian opened this issue May 30, 2017 · 3 comments
Labels
area-core-library SDK core library issues (core, async, ...); use area-vm or area-web for platform specific libraries. core-n library-convert type-enhancement A request for a change that isn't a bug

Comments

@skybrian
Copy link

skybrian commented May 30, 2017

The JsonDecoder constructor takes a reviver that works much the same way as in JavaScript. However, this isn't useful for decoding protobufs (for example) because it doesn't provide enough context.

The type of a protobuf depends on its path from the root, based on JSON map keys. For example, 0->1->2 might be known to be a particular type. The reviver only supplies the last key in the path, which isn't enough to deserialize using a reviver. Instead we construct all the Dart maps and lists for the entire tree, and deserialize it to protobufs as a second pass.

One way to fix would be to add a callback when descending into each map key, so the reviver can maintain a stack.

This API also doesn't declare any types, which means the callback needs to do "is" checks to figure out what's going on. And it also creates maps only to throw them away if you're not reviving a map.

@skybrian
Copy link
Author

skybrian commented May 30, 2017

Here's a strawman proposal:

abstract class JsonReviver {
  // callbacks for reviving map entries
  void startEntry(String key); // called before reviving children of the map entry
  dynamic reviveAtomEntry(String key, atom);
  dynamic reviveListEntry(String key, Iterable items);
  dynamic reviveMapEntry(String key, Iterable<String> keys, Iterable values);

  // callbacks for reviving list items
  void startItem(int index); // called before reviving children of the list item.
  dynamic reviveAtomItem(int index, value);
  dynamic reviveListItem(int index, Iterable items);
  dynamic reviveMapItem(int index, Iterable<String> keys, Iterable values);
}

The idea is to avoid constructing a map only to throw it away; if a map is actually wanted, the reviver can call Map.fromIterables(). Similarly for lists; some JSON encodings use lists to encode things that aren't lists.

Caveat: I used Iterable for clarity but it might not perform the best from a dart2js standpoint due to the large number of implementations; a more specific buffer class might work better.

Looking at _JsonListener in convert_patch.dart, this seems feasible on the JavaScript side. I haven't looked at the Dart VM side.

@skybrian skybrian added library-convert area-core-library SDK core library issues (core, async, ...); use area-vm or area-web for platform specific libraries. type-enhancement A request for a change that isn't a bug labels May 30, 2017
@skybrian
Copy link
Author

@jakobr-google

@kevmoo
Copy link
Member

kevmoo commented Jan 17, 2019

Solution proposal: #35693

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-core-library SDK core library issues (core, async, ...); use area-vm or area-web for platform specific libraries. core-n library-convert type-enhancement A request for a change that isn't a bug
Projects
None yet
Development

No branches or pull requests

4 participants