Skip to content

Reading Map objects from JSON array #8

Description

@e-tobi

The use case that drew my attention to json_events is, that I download a large JSON array where I want to process each object in the array one after the other. Loading the whole JSON into memory for parsing is a no-go. I'm new to Dart/Flutter (coming mainly from C#, C++, Python, Ruby) so I was little bit surprised there was no streaming JSON parser (I'm so used to JSON.Net, I'm probably a little bit spoiled :-) So: json_events to the rescue! (Thanks for providing this!)

But using the JsonArrayTraverser / JsonObjectTraverser feels a little "bulky". Wouldn't it be nice, if you could simply get Map<string, dynamic> objects from a JSON-Stream with an array? Then json_serializable can be used to get the objects from it.

I did a quick test, if this is possible - see code below. (That's where I stumbled upon the other issues, I just posted).
Wouldn't something like this be a nice addition to json_events? If you like this idea, I can try to provide a PR for this. The code below is not yet complete. e.g. an array of arrays wouldn't work. So this would need a little bit more time to do it right with unit tests etc..

readJsonObjectAsMap(StreamIterator<JsonEvent> streamIterator) async {
  Queue<dynamic> objectStack = Queue<dynamic>();
  Map<String, dynamic> root = {};
  objectStack.addLast(root);
  String? currentProperty;
  JsonEvent? lastEvent;
  while (objectStack.isNotEmpty) {
    await streamIterator.moveNext();
    print("${streamIterator.current.type} : ${streamIterator.current.value}");
    switch (streamIterator.current.type) {
      case JsonEventType.propertyName:
        currentProperty = streamIterator.current.value;
        break;
      case JsonEventType.propertyValue:
        if (currentProperty != null) {
          objectStack.last[currentProperty] = streamIterator.current.value;
          currentProperty = null;
        }
        break;
      case JsonEventType.beginObject:
        Map<String, dynamic> newObject = {};
        if (currentProperty != null) {
          objectStack.last[currentProperty] = newObject;
        }
        else {
          objectStack.last.add(newObject);
        }
        currentProperty = null;
        objectStack.addLast(newObject);
        break;
      case JsonEventType.endObject:
        objectStack.removeLast();
        break;
      case JsonEventType.beginArray:
        List newArray = [];
        objectStack.last[currentProperty] = newArray;
        currentProperty = null;
        objectStack.addLast(newArray);
        break;
      case JsonEventType.endArray:
        objectStack.removeLast();
        break;
      case JsonEventType.arrayElement:
        // There's a bug that null array element is emitted after an object in an array
        if (lastEvent?.type != JsonEventType.endObject)
        {
          objectStack.last.add(streamIterator.current.value);
        }
        break;
    }
    lastEvent = streamIterator.current;
  }
  return root;
}

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions