jsonstreamgsonjsonstream

How do I Stream a Json array that is within a json object?


I have a really large Json that I need to stream and parse. The source looks like this:

{
    "Report_Entry": [{
            "FirstName": "Brett",
            "Position": "13_Delta Corp",
            "Worker": "Mr Battles"
        },
        {
            "FirstName": "Dan",
            "Position": "13_Delta Corp",
            "Worker": "Mr Brown"
        }]
}

I would like to do something like this:

InputStream inStream = null;
JsonReader reader = null;
Gson gson = null;

gson = new Gson();
inStream = new FileInputStream("C:\\Downloads\\largereportdata.json");

reader = new JsonReader(new InputStreamReader(inStream, "UTF-8"));
List<Message> messages = new ArrayList<Message>();
reader.beginArray();
while (reader.hasNext()) {
    Message message = gson.fromJson(reader, Message.class);
    //Process the message 
}
reader.endArray();
reader.close();

class Message{
    public String First_Name = null;
    public String Position = null;
    public String Worker = null;
}

If i use gson.fromJson for the parent json object of the array, then the whole object is loaded into ONE object with the array inside, but I would like to stream the array out.

The only way I see now is to somehow edit input and remove the parent "Report_Entry" and the trailing braces, which is a terrible way to do it.

Is there a better approach to this?

Unfortunately, the source cannot be changed, and I have to work with this.

Thanks! Daniel


Solution

  • I solved it using Jackson API.

    JsonFactory f = new MappingJsonFactory();
    
            JsonParser jp = new JsonFactory().createParser(new File("C:\\Users\\Downloads\\rootpart.json"));
    
            ObjectMapper mapper = new ObjectMapper();
            ReportData reportData = null;
    
            JsonToken current;
            current = jp.nextToken();
            if (current != JsonToken.START_OBJECT) {
                System.out.println("Error: root should be object: quitting.");
                return;
            }
            while (jp.nextToken() != JsonToken.END_OBJECT) {
                String fieldName = jp.getCurrentName();
                current = jp.nextToken();
                if (fieldName.equals("Report_Entry")) {
                    if (current == JsonToken.START_ARRAY) {
                        while (current != JsonToken.END_ARRAY) {
                            if (current == JsonToken.START_OBJECT) {
                                reportData = mapper.readValue(jp, ReportData.class);
                                System.out.println(reportData.getKey());
                            }
                            current = jp.nextToken();
                        }
                    } else {
                        jp.skipChildren();
                    }
                } else {
                    jp.skipChildren();
                }
    
            }
    

    Thanks!