如何写一个高效的JSON解析器

2023-11-08

市面上90%的解析器,都是逐个字符解析,然后判断是什么内容,解析成什么类型

这种方式无疑会有一种问题,就是解析器会把你不需要的JSON数据,同样处理一遍。

为此,笔者发现了另外一种思路。

例如下面一段JSON:

{
	"d": [{
		"__type": "MdoCommonWs.WsStructures.WsWmsLookupResult",
		"CallResult": {
			"Id": 0,
			"Data": null,
			"ErrorId": 0,
			"ErrorDescription": null
		},
		"Article": {
			"Id": "001",
			"Description": "ANKERMECHANISCH",
			"Unit": "pieces",
			"UnitPrice": 7,
			"MinStock": 0,
			"MaxStock": 0,
			"Info": "ANKERMECHANISCHM12",
			"Photo": [],
			"PhotoUrl": "",
			"WeightUnit": "kg",
			"Weight": 0.05,
			"CountStock": 0
		},
		"Locations": [{
			"LocationId": "00.00.AA.01.01.01.02",
			"Type": 0,
			"IsBlocked": false,
			"ArticleId": "001",
			"Stock": 2,
			"TotalStock": 2,
			"LastActionDate": "/Date(1480334382093)/",
			"LastInventoryDate": "/Date(1480334319527)/"
		}]
	}],
	"s": [1, 2, 3]
}

怎么样,是不是很复杂。如果它变成下面的JSON后呢?

{
	"d": #aaaaa,
	"s": #bbbbb
}

没错,你一眼就能看出来这是一个object,然后用逗号分隔一下,很容易就能获取两个键值对。分别是d:#aaaaa和s:#bbbbb,这样你在获取d的对象时,再去解析d的内容就行了,根本不用去管s是什么。

笔者的方法,就是先把JSON里面的对象({})和数组([])全部替换掉,这样就能得到一个最简单的对象或数组。而那些被替换的内容,只要缓存起来就行,解析的时候再取出来就可以了。

下面是核心的替换代码:

/**
	 * 将json字符串转成块 例{"userid":[1,2,3]}会被转成{"userid":#1669281915687}
	 * 
	 * @param temp
	 *            原始json
	 * @param c1
	 *            块的起始位置
	 * @param c2
	 *            块的终止位置
	 */
	private void replaceJSONBlock(final StringBuffer temp, String c1, String c2) {
		int left = temp.lastIndexOf(c1);
		if (left > -1) {
			int right = temp.indexOf(c2, left);
			if (right > -1) {
				String uniqueKey = JSON.CACHE_PREFIX + System.nanoTime();
				this.cacheMap.put(uniqueKey, temp.substring(left, right + 1));
				temp.replace(left, right + 1, uniqueKey);
				replaceJSONBlock(temp, c1, c2);
			}
		}
	}

这样之后,这个JSON就可以很简单的进行处理了,甚至可以支持最新的JSON5规范。

测试:

long s = System.currentTimeMillis();
System.out.println(
				"self: " + obj.getJSONArray("d").getJSONObject(0).getJSONObject("CallResult").getString("Data"));
		System.out.println("self: " + obj.getJSONArray("d").toJSONString());
		System.out.println("self: " + obj.getJSONArray("s").get(1));
		long s1 = System.currentTimeMillis();
		System.out.println("time:" + (s1 - s));

		com.alibaba.fastjson.JSONObject obj2 = com.alibaba.fastjson.JSON.parseObject(str);
		System.out.println(
				"ali: " + obj2.getJSONArray("d").getJSONObject(0).getJSONObject("CallResult").getString("Data"));
		System.out.println("ali: " + obj2.getJSONArray("d").toJSONString());
		System.out.println("ali: " + obj2.getJSONArray("s").get(1));
		long s2 = System.currentTimeMillis();
		System.out.println("time:" + (s2 - s1));

结果:

self: null
self: [{"__type":"MdoCommonWs.WsStructures.WsWmsLookupResult","CallResult":{"Id":0,"Data":null,"ErrorId":0,"ErrorDescription":null},"Article":{"Id":"001","Description":"ANKER		 M12		 MECHANISCH","Unit":"pieces","UnitPrice":7,"MinStock":0,"MaxStock":0,"Info":"ANKER		 MECHANISCH		 M12","Photo":[],"PhotoUrl":"","WeightUnit":"kg","Weight":0.05,"CountStock":0},"Locations":[{"LocationId":"00.00.AA.01.01.01.02","Type":0,"IsBlocked":false,"ArticleId":"001","Stock":2,"TotalStock":2,"LastActionDate":"/Date(1480334382093)/","LastInventoryDate":"/Date(1480334319527)/"}]}]
self: 2
time:15
ali: null
ali: [{"CallResult":{"ErrorId":0,"Id":0},"__type":"MdoCommonWs.WsStructures.WsWmsLookupResult","Article":{"MinStock":0,"UnitPrice":7,"CountStock":0,"Description":"ANKER\t\t M12\t\t MECHANISCH","MaxStock":0,"WeightUnit":"kg","Photo":[],"Id":"001","PhotoUrl":"","Unit":"pieces","Info":"ANKER\t\t MECHANISCH\t\t M12","Weight":0.05},"Locations":[{"Type":0,"LocationId":"00.00.AA.01.01.01.02","ArticleId":"001","LastInventoryDate":"/Date(1480334319527)/","LastActionDate":"/Date(1480334382093)/","IsBlocked":false,"Stock":2,"TotalStock":2}]}]
ali: 2
time:207

对此,你有什么看法呢?

源码下载 https://gitee.com/yydf/easy-json

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何写一个高效的JSON解析器 的相关文章

  • 如何向我的 Spring MVC REST 服务添加错误?

    如果用户没有输入我正在编码的两个名称 我如何更改 更新来自 Spring MVC 的以下 REST 调用以返回错误 未找到 RequestMapping value name method RequestMethod GET Respons
  • PostgreSQL:有效地将 JSON 数组拆分为行

    我有一个表 表 A 其中包含一个包含 JSON 编码数据的文本列 JSON 数据始终是一个包含一到几千个普通对象的数组 我有另一个表 表 B 其中有几列 包括数据类型为 JSON 的列 我想从表 A 中选择所有行 将 json 数组拆分为其
  • 将类转换为 JSONObject

    我有好几堂这样的课 我想将类转换为 JSONObject 格式 import java io Serializable import com google gson annotations SerializedName public cla
  • 如何在具有现有记录的 json 数据表顶部添加新行

    我试图在数据表顶部添加一行 显示 金额 列的总和 我正在使用 json 数据表 jquery 插件 列表来显示数据表 如何将此行与现有行一起添加到数据表顶部 我认为这段代码会对你有所帮助 var json uid user123 first
  • JsonCpp - 当有 json::Value 对象时,我如何知道它的键名称?

    假设我有这个 Json 文件 id 0 使用 jsoncpp 我可以有一个Json Value通过这样做来对象 Json Value node root 0u id 好的 在代码的其他地方 我明白了node对象 我想从中获取一些信息 我可以
  • 按值对 JSON 进行排序

    我有一个非常简单的 JSON 对象 如下所示 people f name john l name doe sequence 0 title president url google com color 333333 f name micha
  • 将 Laravel 集合/数组转换为 Javascript 数组

    我想将 Laravel 中的数组分配给 JavaScript 数组 我已经从我的AppServiceProvider和 json decoded 它像 View composer function view users Users all
  • 使用 ng-options 在 AngularJS 中使用 JSON 填充 select

    编辑 我的代码实际上确实有效 我只是一个有不相关问题的白痴 感谢大家的意见 所以我有一个 JSON 对象数组 格式如下 id id1 text text1 id id2 text text2 我想使用这些填充 AngularJS 选择字段
  • 如何在 Serde 中(反)序列化强类型 JSON 字典?

    我正在编写一个 Rust 应用程序 它使用公共接口处理来自 TypeScript 客户端的 JSON 消息 我写了一些代码使用serde derive它运行良好 但我不知道如何实现字典 例如 foo data 42 bar data 133
  • 如何为本机启用现有 WCF 服务的 JSONP?

    我有一个现有的服务 如下方法 AspNetCompatibilityRequirements RequirementsMode AspNetCompatibilityRequirementsMode Allowed ServiceBehav
  • 用于检查 Apache Camel XML 中字符串的 JSONPath 表达式

    假设我有一个简单的 json 文件 如下所示 log host blah severity INFO system 1 我正在使用 Apache Camel 它是 Spring XML 来处理和路由 json 文件 我的路由代码看起来像这样
  • Azure 应用服务在配置中添加字符串数组

    Net core 应用程序并在 Azure 应用服务中部署该应用程序 在我的应用程序中 我有一个包含以下内容的应用程序 settings json 文件 Roles Roles Admins Users 我的 ARM 模板中有以下配置 参数
  • 通过 json 模式 Sequelize 定义模型

    我想通过json制作Sequelize模型广告 我在文档中找不到是否可以通过 json 模式进行模型声明 对于这么强大的库 没有这样的功能很奇怪 也许我找错地方了 只是试图找到同一问题的答案 模式示例 类型 对象 模式 http json
  • 使用python将json和文件发送到flask

    我遇到这个问题 我试图在单个函数中向 Flask API 发送 接收一些文件和 JSON 在我的客户端 发件人 上我有 my json to be sent datas var1 var1 var2 var2 my file to be s
  • 如何在 pandas 中读取并标准化以下 json?

    我在 stackoverflow 中使用 pandas 看到了很多 json 读取问题 但我仍然无法解决这个简单的问题 Data session id 0 X061RFWB06K9V 1 5AZ2X2A9BHH5U unix timesta
  • 如何将此数据编码为 JSON 中的父/子结构

    我正在使用 d3 js 将动物 有机体 家族 一次最多 4000 个 可视化为树形图 尽管数据源也可以是目录列表或命名空间对象列表 我的数据如下 json organisms name Hemiptera Miridae Kanakamir
  • 根据 .NET Core 2.1 中的更改重新加载 Serilog JSON 配置

    我目前正在开发 ASP NET Core 2 1 应用程序 并使用 Serilog 进行日志记录 我想在运行时为我的 Serilog 实现重新加载应用程序设置文件 我的目标是在运行时更改日志级别 例如我写入minimumLevelDebug
  • 来自 iPhone/iPad 的 json Web 服务

    有人可以帮助我解决如何从 iphone 或 ipad 使用 json Web 服务的问题吗 这里我的要求是使用 API 密钥实现 json webservice 如果可能的话发布一些教程或示例链接 谢谢 规范的 JSON 处理库是here
  • 包含 contains 的 json 格式查询

    我在 ansible 中有以下 json 输出 active transaction null cores 4 hostname alpha auth wb01 active transaction null cores 4 hostnam
  • jolt变换后json对象的排序

    Input The input json object 所需输出 Event1 Value1 Event2 collection of json objects Event3 The input json object 所以基本上输入 js

随机推荐

  • Verilog实现呼吸灯效果

    呼吸灯的效果采用PWM调波的形式 即快速的改变每个周期的占空比 一个周期内高电平时间占一个周期时间的比值 来实现点亮到熄灭的效果 示意如下图 而关于整个波形图 用50MHz的晶振 从0开始计数到49则为1us 而1ms是1us的1000倍
  • elasticsearch update 无结果

    这个一直不能用 for id in data front res es update index index doc type doc type id id body doc flag 0 print id res break total
  • Android 块设备驱动之二

    将块设备添到系统 添加磁盘和分区到系统中 add diskgendisk函数 register disk add partition 块设备操作 读写操作 请求操作 提交读写请求 将块设备添到系统 调用void blk register r
  • 【Linux】网络编程二:socket简介、字节序、socket地址及地址转换API

    参考连接 https www nowcoder com study live 504 2 16 Linux 网络编程一 网络结构模式 MAC IP 端口 网络模型 协议及网络通信过程简单介绍 Linux 网络编程二 socket简介 字节序
  • JS 终止执行的方法

    一 在function里面 1 return 2 return false 二 非function方法里面 alert before error throw SyntaxError alert after error 三 非function
  • windows下运行pointnet(全)

    放假闲着在家没事 本人突然想跑一下3d深度学习的开山之作 pointnet玩一玩 可是目前网上大部分pointnet的运行教程都是在Ubuntu系统下的 其实本人也曾装过双系统 但是因为我太菜了 在Ubuntu下装完显卡驱动和cuda后切换
  • Linux配置连接wifi功能步骤总结

    1 配置wpa supplicant conf文件 基本内容如下 ctrl interface var run wpa supplicant ctrl interface group 0 update config 1 network ss
  • Visual Studio中输入英文会在字母之间自动增加空格

    现象 不小心按了什么键之后字母之间增加了空格 如下面 在这里插入图片描述 https img blog csdnimg cn b211b973b9c8470fae4402161ddb3935 png 解决办法 针对上面图片中显示的这种英文字
  • 初学Three.js : 场景搭建

    关于Three js 场景搭建的知识 可结合这两篇文章学习 https juejin im post 5ab07d186fb9a028b92cf79d 官方文档 说明 第一篇中给出的three js 我在使用时出现错误 遂引用了官方文档给出
  • win+R键常见命令

    快速启动快捷键 Win R 这个快捷键是 Windows 的一个原生的功能 从 XP 到 Windows 10 都自带了 在使用这个快捷键后 可以打开系统搜索 是一种比较快捷的指令输入方式 系统会弹出一个小窗口让你输入命令 回车后会立即执行
  • 开源音乐播放器!

    导读 音乐是生活的一部分 维基百科关于音乐发展历史的文章有这样一段不错的描述说 全世界所有的人们 包括哪怕是最孤立 与世隔绝的部落 都会有自己的特色音乐 好吧 我们开源人就构成了一个部落 我建议我们的 音乐形式 应该包括开源音乐播放器 在过
  • Spring下集成 3.X 的mongo

    之前的项目中 打算用springmvc 搞个web来方便访问 数据库 当然是用mongo 遇到的问题是 spring下自带的 只支持2 X的 mongo driver 这点 从 只能 get出 DB DBCollection 就可以看出了
  • go使用json

    JavaScript对象表示法 JSON 是一种用于发送和接收结构化信息的标准协议 在类似的协议中 JSON并不是唯一的一个标准协议 XML 7 14 ASN 1和Google的Protocol Buffers都是类似的协议 并且有各自的特
  • 抖音服务器带宽有多大,才能供上亿人同时刷?

    最近看到一个有意思的提问 抖音服务器带宽有多大 为什么能够供那么多人同时刷 今天来给大家科普一下 首先 我们需要了解什么是服务器带宽 服务器带宽指的是数据中心或服务器中心连接到Internet的传输速率 通常用Mbps或Gbps衡量 这决定
  • vue[vue-quill-editor常规使用及样式相关注意事项]

    vue quill editor是当前vue处理富文本相关的使用比较多的一款插件 然而在使用的过程中这款插件还是有不少需要注意的地方 基础使用 npm install vue quill editor save 编写组件 VueQuillE
  • 正则解析SQL表名和SQL类型

    该程序可以对SQL进行解析 对 hint注释 SQL类型 表名 SQL进行解析 import re def extract sql info sql query 正则表达式用于匹配操作类型和表名 i s select insert upda
  • 学习太极创客 — MQTT(六)ESP8266 发布 MQTT 消息

    视频链接 https www bilibili com video BV1Xy4y1z7Mm spm id from autoNext vd source b91967c499b23106586d7aa35af46413 资料链接 http
  • 过来看~/(≧▽≦)/~啦啦啦!!各种书本课后答案!——第二部分:【化学物理】

    各位 注意了 这里的资料非常齐全 希望大家看了之后支持我 谢谢 啦啦啦 http www 3che com fromuid 21434 第二部分 化学物理 http www 3che com forum 26 1 html http www
  • 【数据结构】【项目】BitMap?40亿电话号码如何快速去重?

    目录 前言 实现 完整代码 参考资料 前言 40亿电话号码如何快速去重 我们往往会想到bitmap 数据结构中的 Bitmap 是一种位图索引非常高效的数据结构 用于存储处理大规模数据的位信息 其中每个位对应于一个元素 如果位为1 则表示该
  • 如何写一个高效的JSON解析器

    市面上90 的解析器 都是逐个字符解析 然后判断是什么内容 解析成什么类型 这种方式无疑会有一种问题 就是解析器会把你不需要的JSON数据 同样处理一遍 为此 笔者发现了另外一种思路 例如下面一段JSON d type MdoCommonW