Pedro
Pedro

Reputation: 105

Recursively building a JSON string to jsTree with Jackson

I´ve been trying to build a JSON string in Java using the Jackson library (v.1.7.4, it´s the only one I can use for this project) to the format accepted by jsTree (https://www.jstree.com/docs/json/). I only care about the "text" and "children" properties. Problem is, I´m not getting a working recursive method to do so.

If I have a simple Tree like this one:

    Tree<String> tree = new Tree<String>();
    Node<String> rootNode = new Node<String>("root");
    Node<String> nodeA = new Node<String>("A");
    Node<String> nodeB = new Node<String>("B");
    Node<String> nodeC = new Node<String>("C");
    Node<String> nodeD = new Node<String>("D");
    Node<String> nodeE = new Node<String>("E");

    rootNode.addChild(nodeA);
    rootNode.addChild(nodeB);
    nodeA.addChild(nodeC);
    nodeB.addChild(nodeD);
    nodeB.addChild(nodeE);

    tree.setRootElement(rootNode);

I´d expect my String to be:

 {text: "root", children: [{text:"A", children:[{text:"C", children: []}]}, {text:"B", children: [{text: "D", children: []}, {text:"E", children:[]}]}] }

I´m trying to build the JSON string using the Tree Model from Jackson. My code so far looks something like this:

 public String generateJSONfromTree(Tree<String> tree) throws IOException{
    String json = "";

    ObjectMapper mapper = new ObjectMapper();
    JsonFactory factory = new JsonFactory();
    ByteArrayOutputStream out = new ByteArrayOutputStream(); // buffer to write to string later
    JsonGenerator generator = factory.createJsonGenerator(out, JsonEncoding.UTF8);

    JsonNode rootNode = mapper.createObjectNode();
    JsonNode coreNode = mapper.createObjectNode();          

    JsonNode dataNode = (ArrayNode)generateJSON(tree.getRootElement()); // the tree nodes

    // assembly arrays and objects
    ((ObjectNode)coreNode).put("data", dataNode);
    ((ObjectNode)rootNode).put("core", coreNode);       
    mapper.writeTree(generator, rootNode);

    json  = out.toString();
    return json;
}

 public ArrayNode generateJSON(Node<String> node, ObjectNode obN, ArrayNode arrN){
    // stop condition ?
    if(node.getChildren().isEmpty()){
        arrN.add(obN);
        return arrN;
    }

    obN.put("text", node.getData());
    for (Node<String> child : node.getChildren()){

        // recursively call on child nodes passing the current object node
        obN.put("children", generateJSON(child, obN, arrN));
    }

}

I tried a few variations of that but no success so far. I know the answer is probably simpler than I´m trying, but I´m stuck. Maybe the stop condition is not appropriate or the logic itself (my thought is to try and reuse the ObjectNode and ArrayNode objects on the next call, to "insert" the "children" element (from the json) on the next child node on the tree, so it would be built backwards, but in the end I get null variables ).

My tree and node classes are based on the following : http://sujitpal.blogspot.com.br/2006/05/java-data-structure-generic-tree.html

Upvotes: 6

Views: 1948

Answers (1)

Tomas Zezula
Tomas Zezula

Reputation: 220

Not the best approach, but it gets the job done:

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Iterator;

import com.fasterxml.jackson.core.JsonEncoding;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;

public class TreeApp {

    public String generateJSONfromTree(Tree<String> tree) throws IOException {
        ObjectMapper mapper = new ObjectMapper();
        JsonFactory factory = new JsonFactory();
        ByteArrayOutputStream out = new ByteArrayOutputStream(); // buffer to write to string later
        JsonGenerator generator = factory.createJsonGenerator(out, JsonEncoding.UTF8);

        ObjectNode rootNode = generateJSON(tree.getRootElement(), mapper.createObjectNode());
        mapper.writeTree(generator, rootNode);

        return out.toString();
    }

    public ObjectNode generateJSON(Node<String> node, ObjectNode obN) {
        if (node == null) {
            return obN;
        }

        obN.put("text", node.getData());

        ArrayNode childN = obN.arrayNode();
        obN.set("children", childN);        
        if (node.getChildren() == null || node.getChildren().isEmpty()) {
            return obN;
        }

        Iterator<Node<String>> it = node.getChildren().iterator();
        while (it.hasNext()) {  
            childN.add(generateJSON(it.next(), new ObjectMapper().createObjectNode()));
        }
        return obN;
    }

    public static void main(String[] args) throws IOException {
        Tree<String> tree = new Tree<String>();
        Node<String> rootNode = new Node<String>("root");
        Node<String> nodeA = new Node<String>("A");
        Node<String> nodeB = new Node<String>("B");
        Node<String> nodeC = new Node<String>("C");
        Node<String> nodeD = new Node<String>("D");
        Node<String> nodeE = new Node<String>("E");

        rootNode.addChild(nodeA);
        rootNode.addChild(nodeB);
        nodeA.addChild(nodeC);
        nodeB.addChild(nodeD);
        nodeB.addChild(nodeE);

        tree.setRootElement(rootNode);

        System.out.println(new TreeApp().generateJSONfromTree(tree));
    }
}

Upvotes: 2

Related Questions