有时候我们项目里面需要将树型关系的数据转换成Json格式的String字符串
假设数据库中的数据如下
需要转换后输出的字符串的结果如下(对应的层级的关系)
[
{name:'爷爷',id:'1',content:'老人辈',parentId:'0',expanded: true,children:[
{name:'爸爸',id:'2',content:'长辈',parentId:'1',expanded: true,children:[
{name:'儿子',id:'4',content:'晚辈',parentId:'2',leaf:true},{name:'女儿',id:'5',content:'晚辈',parentId:'2',leaf:true}
]},{name:'叔叔',id:'3',content:'长辈',parentId:'1',leaf:true}
]
}
]
相应的代码资料网上可以找到
1、树节点类
1 import java.util.ArrayList;
2 import java.util.HashMap;
3 import java.util.List;
4 import java.util.Map;
5
6 /**
7 * 树节点类(用于模拟树型结构关系中的节点)
8 */
9 public class TreeNode {
10 public static final String TREENODE_ATTRIBUTE_NAME_NAME = "name"; // 字段属性name
11 public static final String TREENODE_ATTRIBUTE_NAME_ID = "id"; // 字段属性id
12 private Map<String,Object> attributes = new HashMap<String, Object>(); // 字段属性的Map
13
14 private TreeNode parent = null; //当前节点的父节点
15 private List<TreeNode> child = new ArrayList<TreeNode>(); //当前节点的子节点
16 private boolean isCheck = false; //当前节点是否被勾选标志
17
18
19 /*
20 无参构造函数
21 */
22 public TreeNode(){
23 super();
24 }
25
26 /**
27 * 获取/设置 节点的属性name
28 * @return
29 */
30 public String getName() {
31 return (String) attributes.get(TREENODE_ATTRIBUTE_NAME_NAME);
32 }
33 public void setName(String name) {
34 attributes.put(TREENODE_ATTRIBUTE_NAME_NAME,name);
35 }
36
37 /**
38 * 获取/设置 节点的属性id
39 * @return
40 */
41 public String getId() {
42 return (String) attributes.get(TREENODE_ATTRIBUTE_NAME_ID);
43 }
44 public void setId(String id) {
45 attributes.put(TREENODE_ATTRIBUTE_NAME_ID,id);
46 }
47
48 /**
49 * 获取/设置 节点需要在树形结构中显示的信息
50 * @return
51 */
52 public Map<String, Object> getAttributes() {
53 return attributes;
54 }
55 public void setAttributes(Map<String, Object> attributes) {
56 this.attributes = attributes;
57 }
58
59 /**
60 * 获取/设置 节点是否被勾选信息
61 * @return
62 */
63 public boolean isCheck() {
64 return isCheck;
65 }
66 public void setCheck(boolean check) {
67 isCheck = check;
68 }
69
70 /**
71 * 获取/设置 节点父节点信息
72 * @return
73 */
74 public TreeNode getParent() {
75 return parent;
76 }
77 public void setParent(TreeNode parent) {
78 this.parent = parent;
79 }
80
81 /**
82 * 是否存在/获取/设置/添加 节点子节点信息
83 * @return
84 */
85 public boolean hasChildren(){
86 return child.size()>0;
87 }
88 public List<TreeNode> getChild() {
89 return child;
90 }
91 public void setChild(List<TreeNode> child) {
92 this.child = child;
93 }
94 public void addChild(TreeNode treeNode){
95 treeNode.setParent(this);
96 child.add(treeNode);
97 }
98 }
2、树型节点的属性Map类
1 import java.util.HashMap;
2 import java.util.Map;
3
4 /**
5 * 树型节点的属性Map(用于操作节点的各个属性,如name,id)
6 */
7 public class TreeAttributesMap {
8 private Map<String,Object> attributes = new HashMap<>(); //存放属性的Map
9
10 /**
11 * 有参构造函数
12 * @param id
13 * @param name
14 */
15 public TreeAttributesMap(Object id,Object name){
16 attributes.put(TreeNode.TREENODE_ATTRIBUTE_NAME_ID,id);
17 attributes.put(TreeNode.TREENODE_ATTRIBUTE_NAME_NAME,name);
18 }
19
20 /**
21 * 获取属性的Map
22 * @return
23 */
24 public Map<String, Object> getAttributes() {
25 return attributes;
26 }
27
28 /**
29 * 往属性的Map中添加属性
30 * @param name
31 * @param value
32 */
33 public void putAttributes(String name,Object value){
34 attributes.put(name,value);
35 }
36 }
3、定义一些树型结构相关的接口(方便以后拓展)
1 /**
2 * 定义一般普通的树节点的接口
3 */
4 public interface ISimpleTreeNode {
5
6 /**
7 * 每个树节点都具备自身的一些属性
8 * @return
9 */
10 public TreeAttributesMap getTreeAttributesMap();
11 }
1 /**
2 * 定义层级树节点的接口
3 */
4 public interface ILevelTreeNode extends ISimpleTreeNode{
5
6 public int getParentId();
7 public int getId();
8 }
1 public interface ITreeParser<T> {
2 /**
3 * 解析数据
4 * @param data
5 * @return
6 */
7 List<T> parser(Object data);
8 }
4、树类
1 /**
2 * 树类 (根据自身需求对数据进行解析和转换)
3 */
4 public class Tree {
5 private ITreeParser<TreeNode> treeParser;
6 private int treeType; //转换标志(可以拓展)
7 private Object data; //数据源
8
9 /**
10 * 有参构造函数
11 * @param data
12 * @param treeType
13 */
14 public Tree(Object data,int treeType){
15 this.data = data;
16 this.treeType = treeType;
17 }
18
19 /**
20 * 数据转换 data ---> json格式
21 * @return json格式的String
22 */
23 public String toJsonTree(){
24 String json = "";
25 if (treeType == 1){
26 treeParser = new LevelTreeParser();
27 json = toLevelTree();
28 }else if (treeType == 2){
29 //XXX树型结构
30 }else if (treeType == 3){
31 //XXX树型结构
32 }else{
33 //other树型结构
34 }
35 return json;
36 }
37
38 private String toLevelTree(){
39 String jsonString = "";
40 List<TreeNode> nodes = treeParser.parser(data);
41 StringBuffer sb = new StringBuffer();
42 sb.append("[");
43 parserLevelNodeToJson(sb,nodes);
44 sb.append("]");
45 jsonString = sb.toString();
46 return jsonString;
47 }
48
49 private void parserLevelNodeToJson(StringBuffer sb,List<TreeNode> nodes){
50 Iterator<TreeNode> it = nodes.iterator();
51 while(it.hasNext()){
52 TreeNode node = it.next();
53 boolean isLeaf = node.hasChildren();
54 sb.append("{");
55 Map<String,Object> attributes = node.getAttributes();
56 for(String key:attributes.keySet()){
57 Object obj = attributes.get(key);
58 if (obj != null)
59 sb.append(key + ":'" + obj.toString() + "',");
60 }
61 if (isLeaf){
62 sb.append("expanded: true,children: [");
63 parserLevelNodeToJson(sb,node.getChild());
64 if (it.hasNext()){
65 sb.append("]},");
66 }else{
67 sb.append("]}");
68 }
69 }else{
70 if (it.hasNext()){
71 sb.append("leaf:true},");
72 }else{
73 sb.append("leaf:true}");
74 }
75 }
76 }
77 }
78 }
5、层级树状结构解析实现类
1 import java.util.HashMap;
2 import java.util.List;
3 import java.util.Map;
4
5 public class LevelTreeParser implements ITreeParser<TreeNode>{
6
7 private Map<Object,TreeNode> treeNodeMap = new HashMap<Object, TreeNode>();
8 TreeNode root = new TreeNode();
9
10 public List<TreeNode> parser(Object data){
11 //将数据data强转为List<ILevelTreeNode>格式
12 List<ILevelTreeNode> list = (List<ILevelTreeNode>) data;
13 //List<TreeNode> nodes = new ArrayList<TreeNode>();
14
15 //list不为空且大小不为0
16 if (list != null && list.size()>0){
17
18 //加强for循环list
19 for (ILevelTreeNode levelTreeNode:list){
20 TreeNode item = new TreeNode();
21 //获取每个树节点的属性
22 item.setAttributes(levelTreeNode.getTreeAttributesMap().getAttributes());
23 //封装每个树节点
24 treeNodeMap.put(levelTreeNode.getId(),item);
25 }
26 //再次遍历所有的树节点
27 for (ILevelTreeNode levelTreeNode:list){
28 TreeNode parent = treeNodeMap.get(levelTreeNode.getParentId());
29 TreeNode treeNode = treeNodeMap.get(levelTreeNode.getId());
30 if (parent == null){
31 root.addChild(treeNode);
32 }else{
33 parent.addChild(treeNode);
34 }
35 }
36 }
37 return root.getChild();
38 }
39 }
6、解析格式选择类
1 /**
2 * 解析格式选择类 (用于接受数据源并选择解析格式)
3 */
4 public class BaseParser {
5 public static String parserListToLevelTree(List list){
6 Tree tree = new Tree(list,1);
7 return tree.toJsonTree();
8 }
9 }
7、数据库的Model类treeLevel
要实现接口ILevelTreeNode并实现getTreeAttributesMap的方法,把数据库字段对应的类中的属性都封装起来
1 public class treeLevel implements ILevelTreeNode {
2
3 private int id;
4 private int parentId;
5 private String name;
6 private String content;
7
8 @Override
9 public int getId() {
10 return id;
11 }
12
13 public void setId(int id) {
14 this.id = id;
15 }
16
17 @Override
18 public int getParentId() {
19 return parentId;
20 }
21
22 public void setParentId(int parentId) {
23 this.parentId = parentId;
24 }
25
26 public String getName() {
27 return name;
28 }
29
30 public void setName(String name) {
31 this.name = name;
32 }
33
34 public String getContent() {
35 return content;
36 }
37
38 public void setContent(String content) {
39 this.content = content;
40 }
41
42 @Override
43 public TreeAttributesMap getTreeAttributesMap() {
44 TreeAttributesMap treeMap = new TreeAttributesMap(this.id,this.name);
45 treeMap.putAttributes("content",this.content);
46 treeMap.putAttributes("parentId",this.parentId);
47 return treeMap;
48 }
49 }
8、Dao层(查询数据库表中所有的记录)
1 @Mapper
2 public interface MyDao { 3 @Select("SELECT * FROM treelevel")
4 List<treeLevel> getTreeLevelList();
5 }
9、Server层就省略了,最后只要在Controller层提供Server层调用Dao层访问数据库,将返回的结果List传入静态方法BaseParser.parserListToLevelTree()中即可。
最后,总结一下
a.先为自己的树型节点定义好接口,比如每个节点有获取自己的id、父节点id、属性集合等方法。
b.根据数据库字段创建好对应的类的Model,这里Model类需要实现之前定义好节点的接口,便于后面代码的接入。
c.创建好Parser转换类,将传入List形式的数据转换成自己想要的节点链表形式的数据(对每个节点封装好父节点、子节点们和自身属性集合等)。
d.创建好Tree数据选择解析类,将转换好的节点数据集合解析成自己想要的Json格式的String字符串。