将数据库中树类型的表递归转换为json字符串

将数据库中树类型的表递归转换为json字符串

需求:现在有很好的ext树,可以将数据库中的数据显示成很漂亮的树形,而一个瓶颈问题是怎么把数据库中查询得到的数据转换为json的字符串格式。这里的类就是把这样的一个数据类转换为json串。使用到了JsonUtil这个开源的json字符串转换类。

使用到了堆栈的数据结构。

下面是测试类:


 1 package com;
 2 
 3 public class Test {
 4 
 5     /**
 6      * @param args
 7      */
 8     public static void main(String[] args) {
 9 
10         TreeNode root = new TreeNode("root", "整个世界", null);
11         TreeNode node1 = new TreeNode("1", "太阳系", "root");
12         TreeNode node2 = new TreeNode("2", "地球", "1");
13         TreeNode node3 = new TreeNode("3", "火星", "1");
14         TreeNode node4 = new TreeNode("4", "亚洲", "2");
15         TreeNode node5 = new TreeNode("5", "非洲", "2");
16         TreeNode node6 = new TreeNode("6", "51号星球", "9");
17 
18         Tree tree = new Tree();
19         tree.addNode(node1);
20         tree.addNode(node2);
21         tree.addNode(node3);
22         tree.addNode(node4);
23         tree.addNode(node5);
24         tree.addNode(node6);
25 
26         System.out.println(tree.getTreeJson(tree, root));
27 
28     }
29 
30 }
31 

自定义的类:TreeNode 类主要是包含的树的数据结构的必须的元素:id,name,parent(父亲节点id),print(一个辅助的属性,标志是否已经打印过)。

下面是具体TreeNode 类:


 1 package com;
 2 
 3 public class TreeNode {
 4 
 5     private String id;
 6 
 7     private String parent;
 8 
 9     private String name;
10 
11     private int print;
12 
13     public TreeNode(String id, String name, String parent) {
14         this.id = id;
15         this.name = name;
16         this.parent = parent;
17         this.print = 0;
18     }
19 
20     public String getId() {
21         return id;
22     }
23 
24     public void setId(String id) {
25         this.id = id;
26     }
27 
28     public String getParent() {
29         return parent;
30     }
31 
32     public void setParent(String parent) {
33         this.parent = parent;
34     }
35 
36     public String getName() {
37         return name;
38     }
39 
40     public void setName(String name) {
41         this.name = name;
42     }
43 
44     public int getPrint() {
45         return print;
46     }
47 
48     public void setPrint(int print) {
49         this.print = print;
50     }
51 
52 }
53 

下面是最关键的Tree类,主要是把树的节点进行组装形成整个树型,然后再得到json串:


  1 package com;
  2 
  3 import java.util.ArrayList;
  4 import java.util.HashMap;
  5 import java.util.HashSet;
  6 import java.util.Iterator;
  7 import java.util.List;
  8 import java.util.Map;
  9 import java.util.Set;
 10 
 11 public class Tree {
 12     // 一个关于父亲节点和所有孩子们的键值对
 13     private HashMap parentMap = new HashMap();
 14     // 一个关于节点id和节点对象的键值对
 15     private HashMap nodeMap = new HashMap();
 16     // 包含所有节点的list
 17     private ArrayList nodeList = new ArrayList();
 18 
 19     public void addNode(TreeNode node) {
 20         nodeList.add(node);
 21         nodeMap.put(node.getId(), node);
 22         addParentMap(node.getParent(), node);
 23     }
 24 
 25     // 组装成一个节点与父亲id的map
 26     private void addParentMap(String parentId, TreeNode node) {
 27         List list = new ArrayList();
 28         // 如果这个id下面的孩子们
 29         if (!parentMap.containsKey(parentId)) {
 30             list.add(node);
 31             parentMap.put(parentId, list);
 32         } else {
 33             list = (ArrayList) parentMap.get(parentId);
 34             list.add(node);
 35             parentMap.put(parentId, list);
 36         }
 37     }
 38 
 39     // 根据节点id得到节点
 40     private TreeNode getNode(String id) {
 41         return (TreeNode) nodeMap.get(id);
 42     }
 43 
 44     // 返回全部的父亲节点id组成的一个set
 45     public Set getParentSet() {
 46         Set parentSet = new HashSet();
 47         Iterator it = nodeList.iterator();
 48         while (it.hasNext()) {
 49             TreeNode vo = (TreeNode) it.next();
 50             parentSet.add(vo.getParent());
 51         }
 52         return parentSet;
 53     }
 54 
 55     // 查找孩子
 56     public ArrayList getNodesByParentId(String parentId) {
 57         return (ArrayList) parentMap.get(parentId);
 58     }
 59 
 60     // 设置第一层节点。主要把那些找不到父亲的节点主动的放在根节点下面。
 61     private void setFistFloor(TreeNode root) {
 62         Set parentSet = this.getParentSet();
 63         String rootId = root.getId();
 64         // 用来存放不存在的父亲节点的list
 65         ArrayList notExitslist = new ArrayList();
 66         // 下面查找所有的父节点字符串,如果不存在表明应该准备把这些父亲的孩子转存到虚根的下面,作为虚根的孩子
 67         Object[] parents = parentSet.toArray();
 68         for (int temp = 0; temp < parents.length; temp++) {
 69             String tempId = parents[temp].toString();
 70             // 下面找到所有的不存在的父亲节点,放在list里面。
 71             if (this.getNode(tempId) == null && !tempId.equals(root.getId())) {
 72                 notExitslist.add(parents[temp].toString());
 73             }
 74         }
 75         // 下面根据父亲孩子map找到所有的没有找到父亲节点的孩子们,将它们放到虚根的下面。。下面的是当有多个父亲节点不存在的时候进行更改父亲到虚根下面的操作。
 76         Iterator it = notExitslist.iterator();
 77         while (it.hasNext()) {
 78             ArrayList list2 = getNodesByParentId(it.next().toString());
 79             for (int temp = 0; temp < list2.size(); temp++) {
 80                 TreeNode tempNode = (TreeNode) list2.get(temp);
 81                 tempNode.setParent(rootId);
 82                 addParentMap(rootId, tempNode);
 83             }
 84         }
 85     }
 86 
 87     // 返回父亲与孩子们的映射关系
 88     private Map getParentMap() {
 89         return parentMap;
 90     }
 91 
 92     public String getTreeJson(Tree tree, TreeNode root) {
 93         StringBuilder ans = new StringBuilder();
 94         Set parentSet = tree.getParentSet();
 95         Stack stack = new Stack();
 96         
 97         stack.push(root);
 98         tree.setFistFloor(root);
 99         Map map = tree.getParentMap();
100         String result = "";
101         ans.append("[");
102         while (!stack.isEmpty()) {
103             TreeNode e = stack.top();
104             
105             // 得到该父亲的孩子节点们
106             ArrayList childs = (ArrayList) map.get(e.getId());
107             Iterator cIt = childs.iterator();
108             // 设置一个堆栈是否改变的标志位
109             boolean stackChanged = false;
110             // 如果孩子节点循环未结束或者堆栈没有改变,就进行循环孩子节点的操作!
111             while (cIt.hasNext() && (!stackChanged)) {
112                 // 得到孩子节点
113                 TreeNode aChild = (TreeNode) cIt.next();
114                 // 如果节点没有被打印出来就打印
115                 if (aChild.getPrint() == 0) {
116                     // 如果是树枝节点 ,就直接转换成为json字符串
117                     if ((!parentSet.contains(aChild.getId()))) {
118                         ans.append(JsonUtil.bean2json(aChild) + ",");
119                         // 注意节点打印之后有一个逗号!
120                         // ans.append(getExtNodeJsonStr(aChild) + ",");
121                         // 设置节点被打印的标志位。
122                         aChild.setPrint(1);
123                     }
124                     // 如果是非树枝节点就打印一部分字符串,同时入堆栈进行下次的循环
125                     else if (parentSet.contains(aChild.getId())) {
126                         // 使用了一个开源java类用来形成json串。
127                         ans.append(JsonUtil.bean2json(aChild));
128                         // ans.append(getExtNodeJsonStr(aChild));
129                         ans.deleteCharAt(ans.lastIndexOf("}"));
130                         ans.append(",\"children\":[");
131                         // 设置该节点已经打印
132                         aChild.setPrint(1);
133                         // 将该节点推入堆栈
134                         stack.push(aChild);
135                         // 设置堆栈被修改了。将退出当次的while循环。
136                         stackChanged = true;
137                         break;
138                     }
139                 }
140             }
141 
142             // 下面是进行的json数组封闭组串。
143             // 打印完一个父亲的全部孩子们的json串之后删除最后一个逗号。再加上一个"]".同时扔掉该父亲节点。
144             // 注意查询条件最后一个是因为没有打印root这个json串,所以没有必要在后面进行数组的封闭操作!
145             if ((!cIt.hasNext()) && stackChanged == false) {
146                 // 注意打印完父亲之后要进行字符串的封闭操作。
147                 if (e.getPrint() == 1) {
148                     ans.deleteCharAt(ans.lastIndexOf(","));
149                     ans.append("]},");
150                 }
151                 // 将打印完的父亲节点从堆栈中扔掉。
152                 stack.pop();
153             }
154         }
155         // 下面进行整个字符串的封闭操作。
156         ans.deleteCharAt(ans.lastIndexOf(","));
157         ans.append("]");
158         result = ans.toString();
159         return result;
160     }
161 
162 }
163 


注意使用了一个开源的java类,jutil,主要用来形成一个java类的json串。


  1 package com;
  2 
  3 import java.beans.IntrospectionException;
  4 import java.beans.Introspector;
  5 import java.beans.PropertyDescriptor;
  6 import java.math.BigDecimal;
  7 import java.math.BigInteger;
  8 import java.util.List;
  9 import java.util.Map;
 10 import java.util.Set;
 11 
 12 public class JsonUtil {
 13 
 14     public static String object2json(Object obj) {
 15         StringBuilder json = new StringBuilder();
 16         if (obj == null) {
 17             json.append("\"\"");
 18         } else if (obj instanceof String || obj instanceof Integer
 19                 || obj instanceof Float || obj instanceof Boolean
 20                 || obj instanceof Short || obj instanceof Double
 21                 || obj instanceof Long || obj instanceof BigDecimal
 22                 || obj instanceof BigInteger || obj instanceof Byte) {
 23             json.append("\"").append(string2json(obj.toString())).append("\"");
 24         } else if (obj instanceof Object[]) {
 25             json.append(array2json((Object[]) obj));
 26         } else if (obj instanceof List) {
 27             json.append(list2json((List<?>) obj));
 28         } else if (obj instanceof Map) {
 29             json.append(map2json((Map<?, ?>) obj));
 30         } else if (obj instanceof Set) {
 31             json.append(set2json((Set<?>) obj));
 32         } else {
 33             json.append(bean2json(obj));
 34         }
 35         return json.toString();
 36     }
 37 
 38     public static String bean2json(Object bean) {
 39         StringBuilder json = new StringBuilder();
 40         json.append("{");
 41         PropertyDescriptor[] props = null;
 42         try {
 43             props = Introspector.getBeanInfo(bean.getClass(), Object.class)
 44                     .getPropertyDescriptors();
 45         } catch (IntrospectionException e) {
 46         }
 47         if (props != null) {
 48             for (int i = 0; i < props.length; i++) {
 49                 try {
 50                     String name = object2json(props[i].getName());
 51                     String value = object2json(props[i].getReadMethod().invoke(
 52                             bean));
 53                     json.append(name);
 54                     json.append(":");
 55                     json.append(value);
 56                     json.append(",");
 57                 } catch (Exception e) {
 58                 }
 59             }
 60             json.setCharAt(json.length() - 1, '}');
 61         } else {
 62             json.append("}");
 63         }
 64         return json.toString();
 65     }
 66 
 67     public static String list2json(List<?> list) {
 68         StringBuilder json = new StringBuilder();
 69         json.append("[");
 70         if (list != null && list.size() > 0) {
 71             for (Object obj : list) {
 72                 json.append(object2json(obj));
 73                 json.append(",");
 74             }
 75             json.setCharAt(json.length() - 1, ']');
 76         } else {
 77             json.append("]");
 78         }
 79         return json.toString();
 80     }
 81 
 82     public static String array2json(Object[] array) {
 83         StringBuilder json = new StringBuilder();
 84         json.append("[");
 85         if (array != null && array.length > 0) {
 86             for (Object obj : array) {
 87                 json.append(object2json(obj));
 88                 json.append(",");
 89             }
 90             json.setCharAt(json.length() - 1, ']');
 91         } else {
 92             json.append("]");
 93         }
 94         return json.toString();
 95     }
 96 
 97     public static String map2json(Map<?, ?> map) {
 98         StringBuilder json = new StringBuilder();
 99         json.append("{");
100         if (map != null && map.size() > 0) {
101             for (Object key : map.keySet()) {
102                 json.append(object2json(key));
103                 json.append(":");
104                 json.append(object2json(map.get(key)));
105                 json.append(",");
106             }
107             json.setCharAt(json.length() - 1, '}');
108         } else {
109             json.append("}");
110         }
111         return json.toString();
112     }
113 
114     public static String set2json(Set<?> set) {
115         StringBuilder json = new StringBuilder();
116         json.append("[");
117         if (set != null && set.size() > 0) {
118             for (Object obj : set) {
119                 json.append(object2json(obj));
120                 json.append(",");
121             }
122             json.setCharAt(json.length() - 1, ']');
123         } else {
124             json.append("]");
125         }
126         return json.toString();
127     }
128 
129     public static String string2json(String s) {
130         if (s == null)
131             return "";
132         StringBuilder sb = new StringBuilder();
133         for (int i = 0; i < s.length(); i++) {
134             char ch = s.charAt(i);
135             switch (ch) {
136             case '"':
137                 sb.append("\\\"");
138                 break;
139             case '\\':
140                 sb.append("\\\\");
141                 break;
142             case '\b':
143                 sb.append("\\b");
144                 break;
145             case '\f':
146                 sb.append("\\f");
147                 break;
148             case '\n':
149                 sb.append("\\n");
150                 break;
151             case '\r':
152                 sb.append("\\r");
153                 break;
154             case '\t':
155                 sb.append("\\t");
156                 break;
157             case '/':
158                 sb.append("\\/");
159                 break;
160             default:
161                 if (ch >= '\u0000' && ch <= '\u001F') {
162                     String ss = Integer.toHexString(ch);
163                     sb.append("\\u");
164                     for (int k = 0; k < 4 - ss.length(); k++) {
165                         sb.append('0');
166                     }
167                     sb.append(ss.toUpperCase());
168                 } else {
169                     sb.append(ch);
170                 }
171             }
172         }
173         return sb.toString();
174     }
175 

还有一个自己写的堆栈类,比较简单:


 1 package com;
 2 
 3 import java.util.LinkedList;
 4 
 5 public class Stack {
 6     private LinkedList list = new LinkedList();
 7 
 8     public void push(TreeNode v) {
 9         list.addFirst(v);
10     }
11 
12     public void push(Object v) {
13         list.addFirst(v);
14     }
15 
16     public TreeNode top() {
17         return (TreeNode) list.getFirst();
18     }
19 
20     public Object topObj() {
21         return list.getFirst();
22     }
23 
24     public TreeNode pop() {
25         return (TreeNode) list.removeFirst();
26     }
27 
28     public Object popObj() {
29         return list.removeFirst();
30     }
31 
32     public String toString() {
33         return list.toString();
34     }
35 
36     public boolean isEmpty() {
37         return list.isEmpty();
38     }
39 }
40 







你可能感兴趣的:(将数据库中树类型的表递归转换为json字符串)