Parsing JSON file using Jackson in Java and writing information one by one to an single Object

677 Views Asked by At

I am trying to convert the large JSON/JSON-LD file to XML. The JSON file will contain a list of events (not all events are the same and each may have different information/data). I would like to read the events one by one and store the information in a single Object (rather than having different objects for each event). I would like to store it in the form of Parent and Children. As soon as I read one event I would like to convert it to JSON then go to the next one.

I am looking into JACKSON and seems like it fits this. However, I am looking into this particular class TokenBuffer which is actually kind of doing the same. It's reading the JSON file line by line and then trying to see if the incoming element is Array or Object based on that it's making various decisions.

I wanted to confirm if I can use this Class directly to pass my JsonFile and get the Parent and child relationship which will be stored in JsonWriteContext later I can convert it to XML.

Basically, my sample file will have many events in the JSON which I would like to read one by one and then get the element info and its parent-children relationship in a Single Object such as maybe HashMap.

1

There are 1 best solutions below

2
On

After trying some of the things following is my code which will contain the Parent and Child elements from Json:

@Getter
@Setter
@NoArgsConstructor
public class JsonContext {
    private JsonContext parent;
    private String key;
    private String value;
    private int childCount;
    private Map<String, List<JsonContext>> children = new HashMap<String, List<JsonContext>>();

    // Constructor for Children Object
    JsonContext(String key, String value) {
        this.key = key;
        this.value = value;
    }

    // Constructor for Parent Object
    JsonContext(JsonContext parent, String key, String value) {
        this(key, value);
        this.parent = parent;
    }

    // Add child based on incoming element
    public JsonContext addChild(JsonContext context) {
        List<JsonContext> childValues = children.get(context.getKey());
        if (childValues == null) {
            childValues = new ArrayList<JsonContext>();
        }
        childValues.add(context);
        children.put(context.key, childValues);
        childCount++;
        return context;
    }

    // Get the parent and their subsequent children (test purpose only)
    @Override
    public String toString() {
        String s = key + children.entrySet().stream().map(e -> e.getKey() + " -- " + String.join(", ", e.getValue().stream().map(v -> v.toString())
                            .collect(Collectors.toList()))).collect(Collectors.toList());

        if (value.length() > 0) {
            final String chars = value.toString().trim();
            if (chars.length() > 0) {
                s = s + " = " + chars;
            }
        }
        return s;
    }

}

The above is the context file that will store the information. Below is the JSON parser file.

import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.Arrays;

import com.converter.xml2jsonld.test.JSONParser;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;

public class JsonEventsParser {

    private JsonContext context = null;
    private final String[] eventTypes = new String[] { "event1", "event2", "event3", "event4",
                        "event5" };

    public void jsonFileIterator() throws URISyntaxException, JsonParseException, IOException {
        // Get the JSON Factory and parser Object
        JsonFactory jsonFactory = new JsonFactory();
        JsonParser jsonParser = jsonFactory.createParser(new File(JSONParser.class.getClassLoader().getResource("inputJsonFile.json").toURI()));
        JsonToken current = jsonParser.nextToken();

        // Check the first element is Object
        if (current != JsonToken.START_OBJECT) {
            throw new IllegalStateException("Expected content to be an array");
        }

        // Call the method to loop until the end of the events file
        FileNavigator(jsonParser);
    }

    private void FileNavigator(JsonParser jsonParser) throws IOException {

        JsonToken current = jsonParser.getCurrentToken();

        // Loop until the end of the EPCIS events file
        while (jsonParser.nextToken() != JsonToken.END_OBJECT) {

            final JsonToken token = jsonParser.nextToken();
            final String name = jsonParser.getCurrentName();

            // Handling the fields with direct key value pairs
            if ((token == JsonToken.FIELD_NAME || token == JsonToken.VALUE_STRING)) {
                writeFieldName(jsonParser, token);
            }

            // Handling the Object
            if (token == JsonToken.START_OBJECT) {
                writeObjectFields(jsonParser, token);
            }

            // Handling the Array
            if (token == JsonToken.START_ARRAY) {
                writeArrayFields(jsonParser, token);
            }

            if (context != null) {
                if (context.getParent() != null) {
                    context = context.getParent();
                }
            }
        }
        System.out.println(context.getChildren().toString());
    }

    // Method to obtain the STRING field and write into Context
    private void writeFieldName(JsonParser jsonParser, JsonToken token) throws IOException {
        final String key = jsonParser.getCurrentName();
        final String value = jsonParser.getValueAsString();

        // Check for the eventType
        if (context == null && Arrays.asList(eventTypes).contains(value)) {
            context = new JsonContext(key, value);
        } else if (context != null) {
            context = context.addChild(new JsonContext(context, key, value));
        }

    }

    // Method to obtain the OBJECT and write its children into Context
    private void writeObjectFields(JsonParser jsonParser, JsonToken token) throws IOException {

        final String objectParent = jsonParser.getCurrentName() == null ? context.getParent().getKey() : jsonParser.getCurrentName();
        // Add the name of the OBJECT
        if (context == null) {
            context = new JsonContext(jsonParser.getCurrentName(), "Object");
        } else if (context != null) {
            context = context.addChild(new JsonContext(context, objectParent, "Object"));
        }

        token = jsonParser.nextToken();

        // Loop through all elements within OBJECT and add them to its parent
        while (token != JsonToken.END_OBJECT) {
            final String key = jsonParser.getCurrentName();
            token = jsonParser.nextToken();
            // Check for incoming tokens within array and process accordingly
            switch (token) {
            case START_ARRAY:
                writeArrayFields(jsonParser, token);
                break;
            case START_OBJECT:
                writeObjectFields(jsonParser, token);
                break;
            default:
                final String value = jsonParser.getText();
                context = context.addChild(new JsonContext(context, key, value));
                break;
            // throw new RuntimeException("Object : Elements does not match the type
            // (Method: writeObjectFields)");
            }

            context = context.getParent();
            token = jsonParser.nextToken();
        }
    }

    // Method to Obtain the ARRAY and write its children into Context
    private void writeArrayFields(JsonParser jsonParser, JsonToken token) throws IOException {

        final String arrayField = jsonParser.getCurrentName();
        // Add the name of the ARRAY
        if (context == null) {
            context = new JsonContext(arrayField, "Array");
        } else if (context != null) {
            context = context.addChild(new JsonContext(context, arrayField, "Array"));
        }

        token = jsonParser.nextToken();

        // Loop through all ARRAY elements
        while (token != JsonToken.END_ARRAY) {

            switch (token) {
            case START_OBJECT:
                writeObjectFields(jsonParser, token);
                break;
            case VALUE_STRING:
                context = context.addChild(new JsonContext(context, arrayField, jsonParser.getText()));
                break;
            case START_ARRAY:
                writeArrayFields(jsonParser, token);
                break;
            default:
                throw new RuntimeException("Array : Elements does not match the type (Method: writeArrayFields)");
            }

            context = context.getParent();
            token = jsonParser.nextToken();
        }
    }
}