简体   繁体   中英

Change flat column structure data to hierarchical Structure

I am getting a sql resultset in the form of flat data Which is in the following structure

L0|L1|L2|L3|value

n1|o1|p1|c1|3
n1|o1|p1|c2|2
n1|o1|p2|c1|1
n1|o2|p1|c1|0
n2|o2|p1|c1|5

Here L0,L1,L2,Value.. are column names and we can have more L's as well(it is dynamic)
I want it to convert into the following form

[{name:"n1",children:
    [{name:o1,children:
        [{name:"p1",children:
            [{name:"c1",value:3},
            {name:"c2",value:2}]
      },{name:"p2",children:
            [{name:"c1",value:"1"}]
       }],]}.....

I want the result preferably in JSONArray or List structure. Does anyone have algo or Code to do that in Java? Thanks

Recursion is your friend.

The code below builds up the hierarchy from the input data into an intermediate model (A tree of "Nodes").

This is then turned into JSON using a recursive method...

import java.util.HashMap;
import java.util.Map;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

public class Stack {

    public static void main(String[] args) {
        // Can have as many columns as you want, always assume the last column is the value.
        Object[][] dataFromResultSet = {
                { "n1", "o1", "p1", "c1", 3 },      
                { "n1", "o1", "p1", "c2", 2 },      
                { "n1", "o1", "p2", "c1", 1 },      
                { "n1", "o2", "p1", "c1", 0 },      
                { "n2", "o2", "p1", "c1", 5 }      
        };

        Node root = new Node();

        // Add all records to the hierachy
        for (Object[] row : dataFromResultSet) {
            addToHierachy(root, row);
        }

        // Convert hierachy to JSON
        try {
            JSONArray json = convertToJSON(root);
            System.out.println(json);
        } catch (JSONException e) {
            System.out.println("Something went wrong converting hierachy to JSON");
            e.printStackTrace();
        }
    }

    private static void addToHierachy(Node root, Object[] row) {
        Node current = root;

        // Go through each column in the row
        for(Object col : row) {
            // If this column is a string, then it is a Branch node, not a value one
            // (It might be better to iterate through the array using a counter instead 
            //  and change this condition to say "if it isn't the last column"...)
            if(col instanceof String) {
                // Get (or create) the child node for this column
                current = current.getOrCreateChild((String) col);
            } else {
                // Otherwise, set the value
                current.setValue((Integer) col);
            }
        }
    }

    private static JSONArray convertToJSON(Node root) throws JSONException {
        // Use recursion to build the result JSON
        JSONArray array = new JSONArray();

        // Starting at this root, go through all of the child entries
        for(Map.Entry<String, Node> child : root.getChildren().entrySet()) {
            Node childNode = child.getValue();

            // New object for this entry...
            JSONObject object = new JSONObject();
            // Set the name
            object.put("name", child.getKey());

            // Set the value if it is present on this node
            if(childNode.getValue() != null) {
                object.put("value", childNode.getValue());
            }

            // Generate the child hierarchy if it has children
            if(!childNode.getChildren().isEmpty()) {
                JSONArray childHierachy = convertToJSON(childNode);
                object.put("children", childHierachy);
            }

            array.put(object);
        }

        return array;
    }

    // Class used to build the hierarchy
    static class Node {
        // The map of children, LABEL -> NODE
        private Map<String, Node> children = new HashMap<>();
        // The value (kept as null if this does not have a value set)
        private Integer value;

        public Node getOrCreateChild(String key) {
            Node node = children.get(key);

            if(node == null) {
                node = new Node();
                children.put(key, node);
            }

            return node;
        }

        public Map<String, Node> getChildren() {
            return children;
        }

        public Integer getValue() {
            return value;
        }

        public void setValue(int value) {
            this.value = value;
        }
    }
}

Output:

[ {
    "name" : "n1",
    "children" : [ {
        "name" : "o2",
        "children" : [ {
            "name" : "p1",
            "children" : [ {
                "name" : "c1",
                "value" : 0
            } ]
        } ]
    }, {
        "name" : "o1",
        "children" : [ {
            "name" : "p2",
            "children" : [ {
                "name" : "c1",
                "value" : 1
            } ]
        }, {
            "name" : "p1",
            "children" : [ {
                "name" : "c1",
                "value" : 3
            }, {
                "name" : "c2",
                "value" : 2
            } ]
        } ]
    } ]
}, {
    "name" : "n2",
    "children" : [ {
        "name" : "o2",
        "children" : [ {
            "name" : "p1",
            "children" : [ {
                "name" : "c1",
                "value" : 5
            } ]
        } ]
    } ]
} ]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM