多叉树结构: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);
} } } }

看下效果图:

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

多叉树结构:JSON数据解析(二)的更多相关文章

  1. 多叉树结构:JSON数据解析(一)

    多叉树结构:JSON数据解析(一) 最近做一个实时数据搜索引擎的项目中,在项目架构的偏顶层需要写一个JSON数据解析的模块,由于目前JSON解析没有现成统一开源框架可以利用,目前只是手工利用com.a ...

  2. 使用Gson轻松解决复杂结构的Json数据解析

    转载请注明来源: http://blog.csdn.net/kjunchen/article/details/50961803 JSON简介 JSON(JavaScript Object Notati ...

  3. [开源 .NET 跨平台 数据采集 爬虫框架: DotnetSpider] [四] JSON数据解析

    [DotnetSpider 系列目录] 一.初衷与架构设计 二.基本使用 三.配置式爬虫 四.JSON数据解析与配置系统 场景模拟 假设由于漏存JD SKU对应的店铺信息.这时我们需要重新完全采集所有 ...

  4. JSON数据解析 基础知识及链接收集

    JSON数据解析学习 JSON介绍 JSON(JavaScript Object Notation)是一种轻量级的数据交换格式. JSON 是存储和交换文本信息的语法.类似 XML.但是JSON 比 ...

  5. JSON数据解析(转)

    JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,采用完全独立于语言的文本格式,为Web应用开发提供了一种理想的数据交换格式. 本文将主要介绍在Android ...

  6. iOS - JSON 数据解析

     iOS - JSON 数据解析 前言 NS_CLASS_AVAILABLE(10_7, 5_0) @interface NSJSONSerialization : NSObject @availab ...

  7. Silverlight项目笔记7:xml/json数据解析、TreeView、引用类型与数据绑定错误、图片加载、虚拟目录设置、silverlight安全机制引发的问题、WebClient缓存问题

    1.xml/json数据解析 (1)xml数据解析 使用WebClient获取数据,获取到的数据实例化为一个XDocument,使用XDocument的Descendants(XName)方法获得对应 ...

  8. Android学习笔记之JSON数据解析

    转载:Android学习笔记44:JSON数据解析 JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,采用完全独立于语言的文本格式,为Web应用开发提供了一种 ...

  9. Jquery Ajax和getJSON获取后台普通Json数据和层级Json数据解析

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

随机推荐

  1. mongodb3.0 性能測试报告 二

    mongodb3.0 性能測试报告 一 mongodb3.0 性能測试报告 二 mongodb3.0 性能測试报告 三 測试环境: 服务器:X86 pcserver   共6台 cpu:  单颗8核 ...

  2. Django-form组件补充

    首先来看一个用户登录的实例 from django.forms import Form from django.forms import fields from django.forms import ...

  3. IP分配及网段划分

    1.IP我们先来了解一下3类常用的IP A类IP段 0.0.0.0 到127.255.255.255  B类IP段 128.0.0.0 到191.255.255.255  C类IP段 192.0.0. ...

  4. ffmpeg api升级到3.3 api变化

     void av_free_packet(AVPacket * pkt) Use void av_packet_unref(AVPacket * pkt) Wipe the packet. Unref ...

  5. Oracle 一行拆分为多行

    测试数据: CREATE TABLE t (str VARCHAR2(30)); INSERT INTO t VALUES ( 'X,Y,Z' ); INSERT INTO t VALUES ( 'X ...

  6. 构建ASP.NET MVC5+EF6+EasyUI 1.4.3+Unity4.x注入的后台管理系统(62)-EF链接串加密

    前言: 这一节提供一个简单的功能,这个功能看似简单,找了一下没找到EF链接数据库串的加密帮助文档,只能自己写了,这样也更加符合自己的加密要求 有时候我们发布程序为了避免程序外的SQL链接串明文暴露,需 ...

  7. oracle指定访问某表或某视图

    在oracle中,想创建一个账号,然后只能只读地访问指定的表,怎么搞? 一.为特定的表创建视图 创建视图的时候还可以加上过滤条件,连访问哪些数据都可以指定. create or replace vie ...

  8. echarts 饼状图

    说明:这是我做项目时自己写的小例子,里面有冗余的参数. 开发环境 vs2012 asp.net mvc4  c# 1.显示效果 2.HTML代码 <%@ Page Language=" ...

  9. ReentrantLock和Synchronized

    1 synchronized 1.1 一旦没有获取到就只能一直等待 A和B都获取同一个对象锁,如果A获取了,B没有获取到,那么在A释放该锁之前,B只能无穷等待下去. 1.2 synchronized是 ...

  10. Golang RPC 性能测试

    Golang RPC 性能测试 | KDF5000 http://kdf5000.com/2017/03/28/Golang-RPC-性能测试/