简体   繁体   中英

Convert Tree Structure from database to JSON Object in java?

I have a parent child relationship (Tree Structure) in database and I want to traverse it and create a json object out of it.

My Database Parent child relationship structure (Demo Data).

child_id  parent_id   Item_Name
1         1           Country
2         1           Australia
3         2           Victoria
4         2           Queensland
5         1           Canada
6         5           British Columbia
7         6           Vancouver
8         8           Songs
9         8           Song1
10        8           Song2
11        10          lyrics 1st
12        10          lyrics 2nd
13        13          Germany
14        14          England
15        14          London

How this works

if(child_id == parent_id)
{
   // This item is parent. Like Country,Songs,Germany, England
} else {
  // This item is child. Like Australia, Song1, Vancouver etc.
}

Now, I know how to traverse a structure like this, but having trouble converting it to json object's.

Pseudo Code DFS Tree

Get all parent's

List data = fetch data from table where parent_id=child_id

Now traverse this data

Recursively iterate through child elements

get child_id from data object and query on database it as parent_id, to get its child elements and so on.

However, how to convert it into JSON Object's like this

    {
      "country": [
        {
          "Australia": [
            "Victoria",
            "Queensland"
          ]
        },
        {
          "Canada": [
            {
              "British Columbia": [
                "Vancouver"
              ]
            }
          ]
        }
      ]
    },
{
      "Songs": [
        "Songs1",
        {
          "Songs2": [
            "lyrics 1st",
            "lyrics 2nd"
          ]
        }
      ]
    },
{
      "Germany": null
    },
    {
      "England": ["London"]
    }

Or a json Object in which parent-child relationship is maintained .

First of all the JSON you have provided is not a valid JSON. So that I have added an parent root node when generating the JSON.

If you had a root node defined in your dataset there will be small change to your structure as you cannot maintain parent_Id = child_id relationship as the current data set.So there will be a modification for the solution also.

First you need to map your data into some parent-child supported data type. I have created Node.java for that purpose. Introduced the addChild method to add children one by one.

import java.util.ArrayList;
import java.util.List;

public class Node
{
    private String nodeName;
    private java.util.List<Node> children = new ArrayList<Node>();

    public Node( String nodeName )
    {
        this.nodeName = nodeName;
    }

    public List<Node> getChildren()
    {
        return children;
    }

    public void setChildren( List<Node> children )
    {
        this.children = children;
    }

    public String getNodeName()
    {
        return nodeName;
    }

    public void setNodeName( String nodeName )
    {
        this.nodeName = nodeName;
    }

    public void addChild( Node node )
    {
        this.children.add( node );
    }
}

And for your original data type, I created Mapping.java

public class Mapping
{
    private int parentId;
    private int childId;
    private String ItemName;

    public Mapping( int parentId, int childId, String itemName )
    {
        this.parentId = parentId;
        this.childId = childId;
        ItemName = itemName;
    }

    public int getParentId()
    {
        return parentId;
    }

    public void setParentId( int parentId )
    {
        this.parentId = parentId;
    }

    public int getChildId()
    {
        return childId;
    }

    public void setChildId( int childId )
    {
        this.childId = childId;
    }

    public String getItemName()
    {
        return ItemName;
    }

    public void setItemName( String itemName )
    {
        ItemName = itemName;
    }
}

Now loading and data and populating the Node objects and getting the final Json is done here. I am using an object reference map here because we cannot guarantee the order of mappings in your database. Since children are assigned to the object reference of the parent, after completing the assignment, we will have our parent-child structure. The two loops are also used for the same reason. We need to ensure map is having all nodes before starting to build the structure.

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ParentChild
{
    public static void main( String[] args )
    {
        List<Mapping> list = new ArrayList<Mapping>();
        list.add( new Mapping( 1, 1, "Country" ) );
        list.add( new Mapping( 1, 2, "Australia" ) );
        list.add( new Mapping( 2, 3, "Victoria" ) );
        list.add( new Mapping( 2, 4, "Queensland" ) );
        list.add( new Mapping( 1, 5, "Canada" ) );
        list.add( new Mapping( 5, 6, "British Columbia" ) );
        list.add( new Mapping( 6, 7, "Vancouver" ) );
        list.add( new Mapping( 8, 8, "Songs" ) );
        list.add( new Mapping( 8, 9, "Song1" ) );
        list.add( new Mapping( 8, 10, "Song2" ) );
        list.add( new Mapping( 10, 11, "lyrics 1st" ) );
        list.add( new Mapping( 10, 12, "lyrics 2nd" ) );
        list.add( new Mapping( 13, 13, "Germany" ) );
        list.add( new Mapping( 14, 14, "England" ) );
        list.add( new Mapping( 14, 15, "London" ) );

        Map<Integer, Node> map = new HashMap<Integer, Node>();

        map.put( -1, new Node( "root" ) ); // give index -1 for the root

        for( Mapping mapping : list )  // keep a map of nodes by child id
        {
            map.put( mapping.getChildId(), new Node( mapping.getItemName() ) );
        }

        for( Mapping mapping : list )
        {
            if( mapping.getParentId() == mapping.getChildId() )
            {
                map.get( -1 ).addChild( map.get( mapping.getChildId() ) ); // add to the root
            }
            else
            {
                Node node = map.get( mapping.getParentId() );
                Node childNode = map.get( mapping.getChildId() );
                node.addChild( childNode ); // add to the relevant parent
            }
        }

        StringBuilder json = new StringBuilder();
        writeJson( map.get( -1 ), json ); // root node is enough
        System.out.println( json );
    }

    private static void writeJson( Node node, StringBuilder json )
    {
        if( node.getChildren().isEmpty() ) // no children. return just the node name
        {
            json.append( "\"" ).append( node.getNodeName() ).append( "\"" );
        }
        else
        {
            json.append( "{\"" ).append( node.getNodeName() ).append( "\": [" );

            List<Node> children = node.getChildren();
            for( int i = 0; i < children.size(); i++ )
            {
                Node child = children.get( i );
                writeJson( child, json ); // call recursively
                if( i != children.size() - 1 ) // skip , for the last child
                {
                    json.append( "," );
                }
            }
            json.append( "]}" );
        }
    }
}

I have used a recursive method to build the json.

The resulting JSON

{
   "root":[
      {
         "Country":[
            {
               "Australia":[
                  "Victoria",
                  "Queensland"
               ]
            },
            {
               "Canada":[
                  {
                     "British Columbia":[
                        "Vancouver"
                     ]
                  }
               ]
            }
         ]
      },
      {
         "Songs":[
            "Song1",
            {
               "Song2":[
                  "lyrics 1st",
                  "lyrics 2nd"
               ]
            }
         ]
      },
      "Germany",
      {
         "England":[
            "London"
         ]
      }
   ]
}

Hope it helps.

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