Search code examples
javajsonobjectmapper

Parsing JSon String using json node


i have a normal json string to parse :

"name":"Jake",
"salary":3000,
"phones":[{"phoneType":"cell","phoneNumber":"111-111-111"},
            {"phoneType":"work","phoneNumber":"222-222-222"}],
"taskIds":[11,22,33],
"address":{"street":"101 Blue Dr","city":"White Smoke"}}

i want to create list of objects from this json and save it to database. here is my model :

public class Model {
    private long id;
    private String nodeName;
    private String nodeType;
    private String nodeValue;
    private Model parent; 
}

and this is THE FULL JAVA CODE I HAVE code i tried it:

public class TreeModelParser {

    static List<Model> models = new ArrayList<Model>();
    static Model model;
    static int id = 0;
    static boolean first = true;
    static int nbr = 0;
    static int nbr2 = 0;
    static List<JsonNode> parsedNodes;

    public static void main(String[] args) throws IOException {
        String inputJson = "{\"name\":\"Jake\",\"salary\":3000,\"phones\":"
                + "[{\"phoneType\":\"cell\",\"phoneNumber\":\"111-111-111\"},"
                + "{\"phoneType\":\"work\",\"phoneNumber\":\"222-222-222\"}]," + "\"taskIds\":[11,22,33],"
                + "\"address\":{\"street\":\"101 Blue Dr\",\"city\":\"White Smoke\"}}";
        ObjectMapper objectMapper = new ObjectMapper();
        JsonNode rootNode = objectMapper.readTree(inputJson);
        models = new ArrayList<Model>();
        model = new Model();
        traverse(rootNode, 1);
        for (Model mod : models) {
            System.out.println(
                    mod.getId() + "-" + mod.getNodeName() + "-" + mod.getNodeType() + "-" + mod.getNodeValue());
        }

    }

    private static void traverse(JsonNode node, int level) {
        if (node.getNodeType() == JsonNodeType.ARRAY) {
            traverseArray(node, level);
        } else if (node.getNodeType() == JsonNodeType.OBJECT) {
            traverseObject(node, level);

        } else {
            throw new RuntimeException("Not yet implemented");
        }
    }

    private static void traverseObject(JsonNode node, int level) {
        Iterator<String> fieldNames = node.fieldNames();
        List<String> lst = getListFromIterator(fieldNames);
        for (String fieldName : lst) {
            JsonNode childNode = node.get(fieldName);
            printNode(childNode, fieldName, level);
            if (traversable(childNode)) {
                traverse(childNode, level + 1);
            }
        }
    }

    private static void traverseArray(JsonNode node, int level) {
        for (JsonNode jsonArrayNode : node) {
            printNode(jsonArrayNode, "arrayElement", level);

            if (traversable(jsonArrayNode)) {
                traverse(jsonArrayNode, level + 1);
            }
        }
    }

    private static boolean traversable(JsonNode node) {
        return node.getNodeType() == JsonNodeType.OBJECT || node.getNodeType() == JsonNodeType.ARRAY;
    }

    private static void printNode(JsonNode node, String keyName, int level) {
        model = new Model();
        id++;
        model.setId(id);
        model.setNodeName(keyName);

        if (node.getNodeType().equals(JsonNodeType.ARRAY)) {
            model.setNodeType("ARRAY");
        } else if (node.getNodeType().equals(JsonNodeType.STRING)) {
            model.setNodeType("STRING");
        } else if (node.getNodeType().equals(JsonNodeType.NUMBER)) {
            model.setNodeType("NUMBER");
        } else if (node.getNodeType().equals(JsonNodeType.OBJECT)) {
            model.setNodeType("OBJECT");
        } else if (node.getNodeType().equals(JsonNodeType.BOOLEAN)) {
            model.setNodeType("BOOLEAN");
        }
        if (traversable(node)) {

        } else {
            Object value = null;
            if (node.isTextual()) {
                value = node.textValue();
                model.setNodeValue((String) value);
            } else if (node.isNumber()) {
                value = node.numberValue();
                model.setNodeValue((Number) value + "");
            }

        }
        models.add(model);
    }

    public static List<String> getListFromIterator(Iterator<String> iterator) {
        List<String> list = new ArrayList<>();
        iterator.forEachRemaining(list::add);
        return list;
    }

}

WHEN i run this code i almost get what i want:

1-name-STRING-Jake-null
2-salary-NUMBER-3000-null
3-phones-ARRAY-null-null
4-arrayElement-OBJECT-null-null
5-phoneType-STRING-cell-null
6-phoneNumber-STRING-111-111-111-null
7-arrayElement-OBJECT-null-null
8-phoneType-STRING-work-null
9-phoneNumber-STRING-222-222-222-null
10-taskIds-ARRAY-null-null
11-arrayElement-NUMBER-11-null
12-arrayElement-NUMBER-22-null
13-arrayElement-NUMBER-33-null
14-address-OBJECT-null-null
15-street-STRING-101 Blue Dr-null
16-city-STRING-White Smoke-null

PROBLEM is i have no idea how i can put the PARENT of each object(node). i really cant find any solution.


Solution

  • It will be much easier if we move List<Model> models and Model model properties to method and pass them every time it is needed. Instead of passing level which is not required we can pass Model parent argument which will be a parent object for given node:

    import com.fasterxml.jackson.databind.JsonNode;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.fasterxml.jackson.databind.node.JsonNodeType;
    
    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.List;
    
    public class JsonModelApp {
    
        public static void main(String[] args) throws Exception {
            String inputJson = "{\"name\":\"Jake\",\"salary\":3000,\"phones\":"
                    + "[{\"phoneType\":\"cell\",\"phoneNumber\":\"111-111-111\"},"
                    + "{\"phoneType\":\"work\",\"phoneNumber\":\"222-222-222\"}]," + "\"taskIds\":[11,22,33],"
                    + "\"address\":{\"street\":\"101 Blue Dr\",\"city\":\"White Smoke\"}}";
            ObjectMapper objectMapper = new ObjectMapper();
            JsonNode rootNode = objectMapper.readTree(inputJson);
    
            List<Model> models = new TreeModelParser().traverse(rootNode);
            for (Model mod : models) {
                System.out.println(mod + " => Parent: " + mod.getParent());
            }
        }
    }
    
    class TreeModelParser {
    
        private int id = 0;
    
        public List<Model> traverse(JsonNode root) {
            Model parent = new Model();
            parent.setNodeName("ROOT");
    
            List<Model> models = new ArrayList<>();
            traverse(models, root, parent);
            return models;
        }
    
        private void traverse(List<Model> models, JsonNode node, Model parent) {
            if (node.getNodeType() == JsonNodeType.ARRAY) {
                traverseArray(models, node, parent);
            } else if (node.getNodeType() == JsonNodeType.OBJECT) {
                traverseObject(models, node, parent);
    
            } else {
                throw new RuntimeException("Not yet implemented");
            }
        }
    
        private void traverseObject(List<Model> models, JsonNode node, Model parent) {
            Iterator<String> fieldNames = node.fieldNames();
            List<String> lst = getListFromIterator(fieldNames);
            for (String fieldName : lst) {
                JsonNode childNode = node.get(fieldName);
                Model model = createModel(childNode, fieldName, parent);
                models.add(model);
                if (traversable(childNode)) {
                    traverse(models, childNode, model);
                }
            }
        }
    
        private void traverseArray(List<Model> models, JsonNode node, Model parent) {
            for (JsonNode jsonArrayNode : node) {
                Model model = createModel(jsonArrayNode, "arrayElement", parent);
                models.add(model);
                if (traversable(jsonArrayNode)) {
                    traverse(models, jsonArrayNode, model);
                }
            }
        }
    
        private static boolean traversable(JsonNode node) {
            return node.getNodeType() == JsonNodeType.OBJECT || node.getNodeType() == JsonNodeType.ARRAY;
        }
    
        private Model createModel(JsonNode node, String keyName, Model parent) {
            Model model = new Model();
            model.setId(++id);
            model.setNodeName(keyName);
            model.setParent(parent);
    
            if (node.getNodeType().equals(JsonNodeType.ARRAY)) {
                model.setNodeType("ARRAY");
            } else if (node.getNodeType().equals(JsonNodeType.STRING)) {
                model.setNodeType("STRING");
            } else if (node.getNodeType().equals(JsonNodeType.NUMBER)) {
                model.setNodeType("NUMBER");
            } else if (node.getNodeType().equals(JsonNodeType.OBJECT)) {
                model.setNodeType("OBJECT");
            } else if (node.getNodeType().equals(JsonNodeType.BOOLEAN)) {
                model.setNodeType("BOOLEAN");
            }
            if (!traversable(node)) {
                Object value;
                if (node.isTextual()) {
                    value = node.textValue();
                    model.setNodeValue((String) value);
                } else if (node.isNumber()) {
                    value = node.numberValue();
                    model.setNodeValue(value + "");
                }
    
            }
    
            return model;
        }
    
        private static List<String> getListFromIterator(Iterator<String> iterator) {
            List<String> list = new ArrayList<>();
            iterator.forEachRemaining(list::add);
            return list;
        }
    
    }
    
    class Model {
        private long id;
        private String nodeName;
        private String nodeType;
        private String nodeValue;
        private Model parent;
    
        public long getId() {
            return id;
        }
    
        public void setId(long id) {
            this.id = id;
        }
    
        public String getNodeName() {
            return nodeName;
        }
    
        public void setNodeName(String nodeName) {
            this.nodeName = nodeName;
        }
    
        public String getNodeType() {
            return nodeType;
        }
    
        public void setNodeType(String nodeType) {
            this.nodeType = nodeType;
        }
    
        public String getNodeValue() {
            return nodeValue;
        }
    
        public void setNodeValue(String nodeValue) {
            this.nodeValue = nodeValue;
        }
    
        public Model getParent() {
            return parent;
        }
    
        public void setParent(Model parent) {
            this.parent = parent;
        }
    
        @Override
        public String toString() {
            final StringBuilder sb = new StringBuilder("Model{");
            sb.append("id=").append(id);
            sb.append(", nodeName='").append(nodeName).append('\'');
            sb.append(", nodeType='").append(nodeType).append('\'');
            if (nodeValue != null) {
                sb.append(", nodeValue='").append(nodeValue).append('\'');
            }
            sb.append('}');
            return sb.toString();
        }
    }
    

    Above code prints:

    Model{id=1, nodeName='name', nodeType='STRING', nodeValue='Jake'} => Parent: Model{id=0, nodeName='ROOT', nodeType='null'}
    Model{id=2, nodeName='salary', nodeType='NUMBER', nodeValue='3000'} => Parent: Model{id=0, nodeName='ROOT', nodeType='null'}
    Model{id=3, nodeName='phones', nodeType='ARRAY'} => Parent: Model{id=0, nodeName='ROOT', nodeType='null'}
    Model{id=4, nodeName='arrayElement', nodeType='OBJECT'} => Parent: Model{id=3, nodeName='phones', nodeType='ARRAY'}
    Model{id=5, nodeName='phoneType', nodeType='STRING', nodeValue='cell'} => Parent: Model{id=4, nodeName='arrayElement', nodeType='OBJECT'}
    Model{id=6, nodeName='phoneNumber', nodeType='STRING', nodeValue='111-111-111'} => Parent: Model{id=4, nodeName='arrayElement', nodeType='OBJECT'}
    Model{id=7, nodeName='arrayElement', nodeType='OBJECT'} => Parent: Model{id=3, nodeName='phones', nodeType='ARRAY'}
    Model{id=8, nodeName='phoneType', nodeType='STRING', nodeValue='work'} => Parent: Model{id=7, nodeName='arrayElement', nodeType='OBJECT'}
    Model{id=9, nodeName='phoneNumber', nodeType='STRING', nodeValue='222-222-222'} => Parent: Model{id=7, nodeName='arrayElement', nodeType='OBJECT'}
    Model{id=10, nodeName='taskIds', nodeType='ARRAY'} => Parent: Model{id=0, nodeName='ROOT', nodeType='null'}
    Model{id=11, nodeName='arrayElement', nodeType='NUMBER', nodeValue='11'} => Parent: Model{id=10, nodeName='taskIds', nodeType='ARRAY'}
    Model{id=12, nodeName='arrayElement', nodeType='NUMBER', nodeValue='22'} => Parent: Model{id=10, nodeName='taskIds', nodeType='ARRAY'}
    Model{id=13, nodeName='arrayElement', nodeType='NUMBER', nodeValue='33'} => Parent: Model{id=10, nodeName='taskIds', nodeType='ARRAY'}
    Model{id=14, nodeName='address', nodeType='OBJECT'} => Parent: Model{id=0, nodeName='ROOT', nodeType='null'}
    Model{id=15, nodeName='street', nodeType='STRING', nodeValue='101 Blue Dr'} => Parent: Model{id=14, nodeName='address', nodeType='OBJECT'}
    Model{id=16, nodeName='city', nodeType='STRING', nodeValue='White Smoke'} => Parent: Model{id=14, nodeName='address', nodeType='OBJECT'}