Skip to content

Reading Map objects from JSON array #8

@e-tobi

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

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