zoukankan      html  css  js  c++  java
  • 多叉树结构:JSON数据解析(二)

    多叉树结构:JSON数据解析(二)


            在上篇文章中提到了JSON数据解析的基本方法,但是方法效率太低,这里接着上篇文章写写如何利用多叉树结构,定义对象,实现JSON数据字段快速随机访问。

    JSON数据通常就是无根节点的多叉树结构,对于这种无根节点的多叉树,要实现快速随机访问得经历两个过程:隐式构造根节点,建立多叉树和遍历多叉树。


    3.2 优化的方法——无根节点多叉树随机访问

            对于json的这种数据结构,目前大多数人的做法都是利用list,或者LinkedHashMap去实现,一层层地map套map的结构,非常麻烦。

            其实仔细分析下json样本数据的结构就可以知道,其实很多json数据格式都是个没有根节点的多叉树,那么为什么不构造一个隐式的根节点呢?剩下的就是构造多叉树和多叉树的遍历过程了。

            并且在随机访问方面,任意给定一个节点,我可以拿到该节点作为子树下所有节点,并且后续还可以扩展为另一种形式:通过节点拿到其所有同名兄弟节点(同层同名字段)。

    分析下节点的分类:1.(只有值)无子节点;

                                        2.(有值)有子节点:

                                                     2.1 有单子节点”ss_”开头标记

                                                     2.2 有多值节点”bb_”开头标记

            定义几个节点对象,作为基础数据结构实现:


            下面开始构建多叉树,然后遍历多叉树打印输出节点:

    import java.io.File;
    import java.io.IOException;
    //import java.util.Iterator;
    //import java.util.LinkedHashMap;
    import org.apache.commons.io.FileUtils;
    import com.alibaba.fastjson.JSONArray;
    import com.alibaba.fastjson.JSONObject;
    import com.data.jsontrans.entity.*;
    
    public class BuildTreeAction {
    	
    	RootNode root = new RootNode();
    	//SingleNode singlenode = new SingleNode();
    	//MultiNode multinode = new MultiNode();
    	//root.getChilds().add(singlenode);
    	//root.getChilds().add(multinode);
    	
    	public static void main(String[] args) throws IOException{
    		GetData();
    	}
    	
    	public static void GetData() throws IOException{
    		BuildTreeAction bdtree = new BuildTreeAction();
    		String json = FileUtils.readFileToString(new File("e:/data/json4.txt"));
    		JSONObject jsono = JSONObject.parseObject(json);
    		JSONObject b = jsono.getJSONObject("aggregations");
    		//bdtree.buildResult(b);
    		bdtree.BuildTree(b);
    		
    		Node node;
    		node = bdtree.CreateTree(b);
    	}
    	
    	public Node CreateTree(JSONObject b){
    		SingleNode snode = new SingleNode();
    		MultiNode mnode = new MultiNode();
    		RootNode rnode = new RootNode();
    		
    		return rnode;
    	}
    	
    	public void BuildTree(JSONObject b){
    		for(String key : b.keySet()){						
    			if(key.startsWith("bb_")){
    				MultiNode multinode = new MultiNode();
    				root.getChilds().add(multinode);
    				if(key.equals("bb_appId")){
    					multinode.setNodeId("bb_appId");
    					JSONObject buckets = b.getJSONObject(key);
    					JSONArray bArray = buckets.getJSONArray("buckets");
    					for(int i=0; i<bArray.size(); i++){
    						JSONObject o = bArray.getJSONObject(i);
    						multinode.setKey(o.get("key").toString());
    						multinode.setDoc_count(o.get("doc_count").toString());
    						System.out.println("key:"+multinode.key); //key:UZ6958037483314
    						System.out.println("doc_count:"+multinode.doc_count); //doc_count:361
    												
    						for(String sub1_key : o.keySet()){
    							if(sub1_key.startsWith("bb_")){
    								MultiNode sub1_multinode = new MultiNode();
    								multinode.getChilds().add(sub1_multinode); //在bb_appId的multinode加上子节点"bb_?"
    								if(sub1_key.equals("bb_versionCode")){																	sub1_multinode.setNodeId("bb_versionCode");
    									JSONObject sub1_buckets = o.getJSONObject(sub1_key);
    									JSONArray sub1_bArray = sub1_buckets.getJSONArray("buckets");
    									for(int j=0; j<sub1_bArray.size(); j++){
    										JSONObject o1 = sub1_bArray.getJSONObject(j);
    										sub1_multinode.setKey(o1.get("key").toString());
    										sub1_multinode.setDoc_count(o1.get("doc_count").toString());
    										System.out.println("key:" + sub1_multinode.key);
    										System.out.println("doc_count:" + sub1_multinode.doc_count);
    										
    										for(String sub2_key : o1.keySet()){
    											if(sub2_key.startsWith("bb_")){
    												MultiNode sub2_multinode = new MultiNode();
    												sub1_multinode.getChilds().add(sub2_multinode); //在bb_versionCode的sub1_multinode加上多子节点												
    												if(sub2_key.equals("bb_isNewVersion")){
    													multinode.setNodeId("bb_isNewVersion");
    													JSONObject sub2_buckets = o.getJSONObject(key);
    													JSONArray sub2_bArray = sub2_buckets.getJSONArray("buckets");
    													for(int k=0; k<sub2_bArray.size(); k++){
    														JSONObject o2 = sub2_bArray.getJSONObject(k);
    														multinode.setKey(o2.get("key").toString());
    														multinode.setDoc_count(o2.get("doc_count").toString());
    														System.out.println("key:"+multinode.key);
    														System.out.println("doc_count:"+multinode.doc_count);
    													}
    												}
    												else if(sub2_key.equals("bb_isNew")){
    													sub2_multinode.setNodeId("bb_isNew");
    													JSONObject sub2_buckets = o1.getJSONObject(sub2_key);
    													JSONArray sub2_bArray = sub2_buckets.getJSONArray("buckets");													
    													for(int k=0; k<sub2_bArray.size(); k++){
    														JSONObject o2 = sub2_bArray.getJSONObject(k);
    														sub2_multinode.setKey(o2.get("key").toString());
    														sub2_multinode.setDoc_count(o2.get("doc_count").toString());
    														System.out.println("key:"+sub2_multinode.key);
    														System.out.println("doc_count:"+sub2_multinode.doc_count);
    													}
    												}
    												
    											}
    											else if(sub2_key.startsWith("ss_")){
    												SingleNode sub2_singlenode = new SingleNode();
    												sub1_multinode.getChilds().add(sub2_singlenode); //在bb_versionCode的sub1_multinode加上单子节点
    												if(sub2_key.equals("ss_usercount")){
    													sub2_singlenode.setNodeId("ss_usercount");
    													sub2_singlenode.getSnode().setNodeId("value");
    													sub2_singlenode.getSnode().value = o1.getJSONObject("ss_usercount").getString("value");
    													System.out.println("ss_appId: "+"value:"+sub2_singlenode.getSnode().value);
    												}
    												
    											}											
    										}
    										
    									}
    								}
    								/*else if(subkey1.equals("bb_versionId")){
    									//同上处理...
    								}*/								
    							}
    							else if(sub1_key.startsWith("ss_")){
    								SingleNode sub1_singlenode = new SingleNode();
    								multinode.getChilds().add(sub1_singlenode); //在bb_appId的multinode加上子节点"ss_?"
    								if(sub1_key.equals("ss_versionCode")){
    									sub1_singlenode.setNodeId("ss_versionCode");
    									sub1_singlenode.getSnode().setNodeId("value");
    									sub1_singlenode.getSnode().value = o.getJSONObject("ss_appId").getString("value");
    									System.out.println("ss_appId: "+"value:"+sub1_singlenode.getSnode().value);
    								}
    								/*else if(sub1_key.equals("ss_versionId")){
    									//同上处理...
    								}*/
    							}
    						}
    						
    					}
    				}
    				
    			}
    			
    			else if(key.startsWith("ss_")){
    				SingleNode singlenode = new SingleNode();
    				root.getChilds().add(singlenode);
    				ss_mynode(b, key, singlenode, "ss_appId");
    				/*else if(key.equals("ss_usercode")){
    					//...其他"ss_usercode"同上类似处理...//
    				}*/
    				
    			}
    			
    			else{
    				System.out.println("nothing");
    			}
    			
    		}
    	}
    

    运行结果:



    3.3 效率优化——迭代+递归实现

            实际上树的构建和遍历通常用递归实现,这里迭代for循环判断节点就两种类型:单值”ss_”和多值”bb_”节点,这就足够了——for循环迭代+递归。基本思路就是循环依次读取每个节点,每次判断是否单值或多值节点,如果多值节点,继续以其下子节点作为parent再继续递归,传回的参数就是本次节点Node及层级编号。

    import java.io.File;
    import java.io.IOException;
    import java.util.Iterator;
    import java.util.List;
    import java.util.ArrayList;
    //import java.util.LinkedHashMap;
    import org.apache.commons.io.FileUtils;
    import com.alibaba.fastjson.JSONArray;
    import com.alibaba.fastjson.JSONObject;
    import com.data.jsontrans.entity.*;
    
    public class CreateTreeAction {
    	
    	public static void main(String[] args) throws IOException{
    		CreateTreeAction ctree = new CreateTreeAction();
    		String json = FileUtils.readFileToString(new File("e:/data/json4.txt"));
    		JSONObject jsono = JSONObject.parseObject(json);
    		JSONObject b = jsono.getJSONObject("aggregations");
    		Node root = ctree.buildJsonTree(b);
    	}
    	
    	public Node buildJsonTree(JSONObject b){
    		RootNode node = new RootNode(); //通用变量node
    		buildTree(node,b);
    		return node; 
    	}
    
    	public void buildTree(Node parent, JSONObject b) {
    		for(String key : b.keySet()){
    			if(key.startsWith("bb_")){
    				//MultiNode multinode = createMutilNode(b, key);
    				MultiNode multinode = new MultiNode();
    				multinode.setNodeId(key);
    				JSONObject buckets = b.getJSONObject(key); 
    				JSONArray bArray = buckets.getJSONArray("buckets");
    				for(Iterator iterator = bArray.iterator(); iterator.hasNext(); ){
    					JSONObject o = (JSONObject) iterator.next();
    					if(o.get("key_as_string")!=null){
    						multinode.setKey_as_string(o.get("key_as_string").toString());
    						System.out.println(multinode.key_as_string);
    					}
    					multinode.setKey(o.get("key").toString());
    					multinode.setDoc_count(o.get("doc_count").toString());
    					System.out.println(multinode.key);
    					System.out.println(multinode.doc_count);
    					parent.getChilds().add(multinode);
    					buildTree(parent, o);  //迭代计算buildTree()
    				}				
    				//parent.getChilds().add(multinode);
    			}
    			else if(key.startsWith("ss_")){
    				//SingleNode singlenode = createSingleNode(b, key);
    				SingleNode singlenode = new SingleNode();
    				singlenode.setNodeId(key);
    				singlenode.value = b.getJSONObject(key).getString("value");
    				System.out.println("ss_ "+"value:"+singlenode.value);
    				parent.getChilds().add(singlenode);
    			}
    			
    		}
    		
    	}
    
    
    }
    

    看下效果图:



    (原创文章,转载请注明出处)

  • 相关阅读:
    【WebSocket】Qt客户端
    【WebSocket】入门教程(JS)
    【C++ 压缩&解压缩 开源库】ZIP入门使用总结
    【C++ JSON 开源库】nlohmann入门使用总结
    OSS C++ SDK使用总结
    解决Element中table文字过多换行问题
    Xmind安装报错
    Object.assign()
    mousedown、mouseup、click
    el-table 动态控制表格高度
  • 原文地址:https://www.cnblogs.com/DianaCody/p/5425683.html
Copyright © 2011-2022 走看看