概述

附上完整的代码:

https://files.cnblogs.com/files/xcr1234/json.rar

一个类实现json解析核心代码(ObjectParser),其他的类都是工具类
(入口类是Json)

JSON:JavaScript 对象表示法(JavaScript Object Notation)。

JSON 是存储和交换文本信息的语法。类似 XML。

JSON 比 XML 更小、更快,更易解析。

在JSON中,分为6种对象:

  • 数字(整数或浮点数)
  • 字符串(在双引号中)
  • 逻辑值(true 或 false)
  • 数组(JsonArray)
  • 对象(JsonObject)
  • null

基本对象的实现

JsonObject其实就是一个HashMap,JsonArray其实就是一个ArrayList.

public class JsonObject extends HashMap<String,Object> {}public class JsonArray extends ArrayList<Object> {}

JSON字符串的解析

以这个字符串为例:

{“success”:true,”id”:-10.5,”employees”:[{“firstName”:”Bill”,”lastName”:”Gates”},{“firstName”:”George”,”lastName”:”Bush”},{“firstName”:”Thomas”,”lastName”:”Carter”}]}

我们保证在只扫描一次整个的情况下,就将json结构解析成功。

传统的解析策略通常是通过词法分析,将json分为一个个的token,而这些token有着自己的类型和值;再通过语法分析构建一棵抽象语法树,进一步处理。比如""是一种,true/false又是一种。

其实根本不需要这么复杂。依我看来,json的token只有五种:true/false/null(归为一种,因为它们是固定值)、number、string、object、array。也不用特别在意start和end的Token区分,比如 { 符号和 } 符号。从一个 { 符号开始,到下一个它对应的 } 符号都是属于同一个json object的。这里的 { 与 } 、[ 与 ] 符号都是一一对应的。
我设计了一个nextObject()方法,它可以解析出json字符串中的下一个对象,然后在适当的时候装配即可。

nextObject方法的实现

提取字符

    public static boolean isSpace(char c){return c == ' ' || c == '\r' || c == '\n';}//方法得到当前字符,忽略空格、换行符private char getChar(){char c = json.charAt(pos);while(isSpace(c)){pos++;c = getCurrentChar();}return c;}

上面方法是消耗掉所有空白字符,直到读取到一个非空白字符,isSpace方法用于判断一个字符是否属于空白字符,pos表示当前指针指向的那个字符。也就是说,DFA从起始状态开始,若读到一个空字符,会在起始状态不断循环,直到遇到非空字符,状态转移情况如下:

解析

根据提取到的字符,转入不同的解析方法中,

例如字符是t,说明值可能是true,只需检查后面三个字符,如果是r、u、e,则可以直接返回true。

字符是f,说明值可能是false,只需检查后面四个字符,如果是a、l、s、e,则可以直接返回false。

碰到 \”,说明是字符串,在下一个\”出现之前,把扫描出来的字符都当成字符串中的字符,放到一个StringBuilder中去。

碰到 [ 符号,说明是数组了,就需要new一个JsonArray,在下一个 ] 符号出现之前,调用nextObject方法,把解析到的对象都放到这个JsonArray里面去。

碰到 { 符号,说明是JsonObject,就new一个JsonObject,这里每次需要连续调用两次nextObject,第一次结果作为key,第二次结果作为value。放到JsonObject中去。

解析boolean、null值

这类值的字符串只有固定的三种true、false、null,是最好解析的。在扫描到第一个字符为t、f、n时,只需检测后续字符是否符合固定值就可以了。checkChars方法实现了这个功能,chars是固定的序列,如果检测通过则返回true,否则返回false。

private boolean checkChars(char ...chars){for(char ch : chars){char c = getCurrentCharNext();   //得到当前字符,包括空格、换行符。将指针指向下一个字符if(Character.toLowerCase(ch) != Character.toLowerCase(c)){return false;}}return true;}

如果是true,就是`checkChars('t','r','u','e')`

解析数字

解析数字的实现是parseNumber方法,我们先new一个StringBuilder,向后扫描只要碰到0-9或者+-小数点,就添加到这个StringBuilder当中去,否则就StringBuilder.toString,将这个字符串转换成数字。

如果包含小数点,就用double,否则就用integer。

解析字符串

在json中字符串都是以双引号”开头,再以双引号”结尾的。当扫描到双引号”时,new一个StringBuilder,然后在下一个双引号”出现之前的每一个字符都需要添加到这个StringBuilder中去。需要注意的一点,字符串中是可能出现转义字符的。因此在扫描到一个字符为斜杠\时,需要取出下一个字符进行特殊处理。

解析JsonObject

连续调用两次nextObject,第一次结果作为key,第二次结果作为value。放到JsonObject中去。
注意逗号和冒号的处理。

JsonArray的解析

在下一个 ] 符号出现之前,递归调用nextObject方法,把解析到的对象都放到这个JsonArray里面去。

返回

由于nextObject只返回一个对象,我们用nextObject方法处理整个json字符串。那么nextObject方法就会得到你需要的JsonObject。

超大json对象的解析

参考 http://blog.csdn.net/dxiaolai/article/details/76359332

在大数据量的json场景下,不必将整个json字符串全部解析成json object后再处理,而是通过迭代器模式我们可以在解析字符串的同时使用对象。这样可以大大的提高程序的执行效率。

扩展ObjectParser类,使其成为一个迭代器,

public class ObjectParser implements Iterator<Object>{public Object next(){return nextObject();}public boolean hasNext(){return pos < json.length();}@Overridepublic void remove() {}}

这样就可以边解析边使用对象了。

ObjectParser parser = new ObjectParser ("json");
while(parser.hasNext()){Object object = parser.next();
}

超大的json串,通常是以流的方式提供,我们不必要一次性将流字节全部读入内存,而是可以逐字符的解析。每次读取若干个字符,解析成对象;实现方式是使用BuffererReader,修改getChar等方法,每次读字符时从BuffererReader中读取。配合上面的迭代器模式,可考虑将一个BuffererReader封装成Iterator<Object>。

转载于:https://www.cnblogs.com/xcr1234/p/7860069.html

Json字符串解析原理、超大json对象的解析相关推荐

  1. JSON字符串在Java和JavaScript中的解析和转换

    JSON字符串在Java和JS种的转换 1. JSON字符串格式 2. JSON 在 Java 中的转换 2.1 FastJSON 使用 2.2 Jackson 使用 2.3 Gson 使用 2.4 ...

  2. json字符串多了双引号_Python-数据解析-json模块 !

    import json json 一种轻量级的数据交换格式. 一.JSON 的值 数字(整数或浮点数) 字符串(在双引号中) 逻辑值(true 或 false) 数组(在方括号中) 对象(在花括号中) ...

  3. [转]jackson json字符串、map、java对象的转换例子

    ackson框架 json字符串.map.java对象的转换例子 先下载框架jar包: 下面是一些例子: package jackson; import java.io.File; import ja ...

  4. c# 解析json 字符串 报异常 Bad JSON escape sequence 解决方案

    c# 解析json 字符串 报异常 Bad JSON escape sequence 解决方案 参考文章: (1)c# 解析json 字符串 报异常 Bad JSON escape sequence ...

  5. JSON是什么?JSON字符串是什么?JSON对象又是什么?

    什么是JSON?JSON是干什么的? JSON(JavaScript Object Notation, JS 对象简谱) 是一种轻量级的数据交换格式.它基于 ECMAScript (欧洲计算机协会制定 ...

  6. 多层json字符串转map_Java中Json字符串直接转换为对象的方法(包括多层List集合)

    使用到的类:net.sf.json.JSONObject 使用JSON时,除了要导入JSON网站上面下载的json-lib-2.2-jdk15.jar包之外,还必须有其它几个依赖包:commons-b ...

  7. Json对象与Json字符串的转化、JSON字符串与Java对象的转换

    一.Json对象与Json字符串的转化 1.jQuery插件支持的转换方式: $.parseJSON( jsonstr ); //jQuery.parseJSON(jsonstr),可以将json字符 ...

  8. JSON字符串转为指定实体类对象

    创建JsonStringToClass对象即可 package utils;import net.sf.json.JSONArray; import net.sf.json.JSONObject;im ...

  9. json java typeof_Json对象与Json字符串的转化、JSON字符串与Java对象的转换

    一.Json对象与Json字符串的转化 1.jQuery插件支持的转换方式: $.parseJSON( jsonstr ); //jQuery.parseJSON(jsonstr),可以将json字符 ...

  10. python数据存储系列教程——python对象与json字符串的相互转化,json文件的存储与读取

    全栈工程师开发手册 (作者:栾鹏) python教程全解 在json字符串和python对象的相互转化中,会进行下列变换. 会将python中字典的写法,转化为js中对象的写法.(没有区别). 会将p ...

最新文章

  1. plt.xlabel 'str' object is not callable
  2. Nmap 7.70新增功能——扫描主机所有IP
  3. flinksql获取系统当前时间搓_DNF:从剑魂角度看工作服,不仅不是地摊货,更是超越了手搓套...
  4. [我的1024开源程序]100元写的单词本说明书
  5. 禁止遮罩层以下屏幕滑动----正解(更新版)
  6. html所有页面根的对象,在django中显示来自所有用户的对象,无需登录到html页面...
  7. [ActionScript 3.0] NetConnection建立客户端与服务器的双向连接
  8. 2017.6.4 problem b 失败总结
  9. 【黑金动力社区】【bf531 体验板教程】第六章 可编程标志口(八)
  10. html++hint标签,html5新标签总结
  11. mac 修改pip镜像为国内镜像
  12. 如何查看文件md5值
  13. HDOJ 5143 NPY and arithmetic progression DFS
  14. 吴国平:开发旅游小镇是一款养成类游戏 | 十年二十人
  15. 2018年清华大学民商法学考研经验分享
  16. windowsXPsp3恢复桌面IE图标
  17. 1736. Latest Time by Replacing Hidden Digits
  18. 同元软控助力复杂系统数字孪生落地应用
  19. C语言实现大计基作业之某种图灵机
  20. 2542 咖啡和作业 (简单二分)

热门文章

  1. MySQL单表恢复方法
  2. EasyUC博客助手 [支持:博客园,MSN/Live空间,CSDN, 博客之家,PJBlog,Z-Blog...]
  3. Web安全测试检查单
  4. SpringBoot系列: Web应用鉴权思路
  5. bzoj 3100 排列
  6. 记录自己的学习和经验
  7. 什么是 AIDL 以及如何使用
  8. JavaScript错误:Maximum call stack size exceeded错误
  9. 一个不错的js制作的右键菜单
  10. Android 布局错乱 Android花屏