解析JSON的这 6 种方案,真香!

在 Java 开发中,解析 JSON 是一个非常常见的需求。

不管是和前端交互、调用第三方接口,还是处理配置文件,几乎都绕不开 JSON。

这篇文章总结了6种主流的 JSON 解析方法,希望对你会有所帮助。

  • 强大的序列化和反序列化:支持将 JSON 字符串转为 Java 对象,也支持将 Java 对象转换为 JSON。
  • 支持复杂结构:处理嵌套对象、数组、泛型等场景非常轻松。
  • 支持注解:如 @JsonIgnore、@JsonProperty 等,能精细控制序列化与反序列化的行为。
  • 性能高:Jackson 的性能非常出色,是很多企业级项目的首选。

1. JSON 转对象(反序列化)

2. 对象转 JSON(序列化)

  • 日期格式化:@JsonFormat(pattern = \”yyyy-MM-dd\”)
  • 忽略字段:@JsonIgnore
  • 重命名字段:@JsonProperty(\”custom_name\”)

优点缺点功能全面,支持复杂场景配置较多,学习成本稍高性能高,社区活跃,企业级项目首选过于强大,部分功能用不上丰富的注解支持,便于控制序列化行为库体积较大,对于小型项目略显笨重

  • 轻量级:Gson 的设计非常简洁,代码量少,适合中小型项目。
  • 支持泛型:可以轻松解析带泛型的 JSON。
  • 注解控制:支持通过注解控制序列化行为,如 @Expose。
  • 易扩展:通过自定义序列化器和反序列化器,可以处理复杂的场景。

1. JSON 转对象

2. 对象转 JSON

  • 忽略字段:@Expose@Exposeprivate String name;
  • 自定义序列化器/反序列化器:Gson gson = new GsonBuilder().registerTypeAdapter(CustomClass.class, new CustomSerializer()).create();

优点缺点轻量级,简单易用,适合中小型项目性能稍逊于 Jackson学习曲线平滑,新手容易上手功能不如 Jackson 丰富提供良好的扩展能力复杂对象处理起来较为麻烦

  • 性能优异:FastJSON 的解析速度非常快,适合大数据量场景。
  • 支持动态字段:可以轻松处理动态 JSON 数据。
  • 强大的类型支持:支持嵌套对象、泛型、数组等复杂结构。
  • 注解控制:类似 Jackson 和 Gson,支持注解控制字段的序列化和反序列化。

1. JSON 转对象

2. 对象转 JSON

  • 自动驼峰转下划线:JSON.DEFFAULT_DATE_FORMAT = \”yyyy-MM-dd HH:mm:ss\”;
  • 动态字段解析:Map<String, Object> map = JSON.parseObject(json, Map.class);

优点缺点性能极高,解析速度快曾有历史安全漏洞的争议支持复杂的动态字段解析社区活跃度稍逊于 Jackson 和 Gson功能全面,适合大规模数据处理场景配置选项和 API 比较多,稍显复杂

  • 高效字段提取:通过路径表达式(类似 XPath)快速提取嵌套字段。
  • 灵活性强:支持动态字段和条件过滤。
  • 轻量级:专注于字段提取,功能简单明确。

优点缺点字段提取简洁高效不支持序列化和反序列化动态字段处理能力强依赖 JsonPath 语法适合快速提取嵌套字段不适合全量 JSON 转换

  • 轻量级:核心是一个工具类,适合简单场景。
  • 构造和解析简单:适合快速创建 JSON 或提取字段。
  • 灵活性一般:不支持复杂对象映射。

优点缺点轻量级,适合简单场景不支持复杂嵌套对象使用简单,学习成本低功能简单,扩展性差

  • 完全自由:不依赖第三方库,自己解析 JSON。
  • 动态处理:适合不规则字段结构的 JSON。
  • 代码复杂度高:适合特殊场景。

优点缺点灵活性高,适合动态字段代码复杂度高,不易维护不依赖第三方库性能和效率低于专业 JSON 库

最后给大家对比一下文章中提到的6种方法各自的优缺点:

方法适用场景优点缺点Jackson企业级项目,复杂序列化和反序列化场景功能强大,性能优异,支持复杂结构配置复杂,学习曲线高Gson中小型项目,简单的 JSON 转换场景轻量级,简单易用功能有限,性能略逊FastJSON高性能需求,大数据量的动态解析性能极高,功能丰富曾有安全漏洞争议,社区支持稍逊 JacksonJsonPath嵌套结构复杂、动态字段提取场景字段提取语法简单,灵活性强不支持序列化和反序列化org.json快速解析或构造 JSON 场景轻量级,适合简单场景功能单一,扩展性差手动解析动态 JSON 或字段不固定的场景自由度高,灵活性强代码复杂,效率低于专业工具

工具千千万,场景最重要!

选对了工具,才能省时省力,少踩坑多摸鱼。

一款简单易用的 Json 解析库

大家好,又见面了,我是 GitHub 精选君!

在快节奏的开发工作中,处理 JSON 数据是一项常见但往往耗时的任务。无论是解析复杂的 JSON 结构,还是需要在没有固定模式的大型 JSON 文件中查找特定的信息,开发者都面临着效率问题。特别是在 Go 语言中,尽管其标准库提供了强大的 JSON 支持,但在处理复杂或大型 JSON 文档时,依旧可能感到不够灵活和高效。关键的痛点包括但不限于:

1、路径检索复杂性:需要在嵌套的 JSON 结构中快速定位和检索数据,使用传统方法时往往要写大量的代码。

2、效率问题:在大型 JSON 文件中查找特定信息时,性能可能成为瓶颈。

3、代码复杂度:实现复杂的 JSON 数据检索和操作可能使代码变得难以维护和理解。

今天要给大家推荐一个 GitHub 开源项目 gjson,该项目在 GitHub 有超过 14.4k Star。

一句话介绍该项目:Get JSON values quickly – JSON parser for Go

GJSON 是一个为 Go 语言设计的开源包,它通过提供快速简单的方式从 JSON 中获取值来解决上述问题。其特点包括:

1、一行检索:能够通过简单的路径语法,实现对嵌套 JSON 数据的快速访问。

2、点符号路径:支持直观的点符号来定位 JSON 结构中的元素。

3、迭代和解析 JSON 行:简化了遍历 JSON 对象或数组,以及解析多行 JSON 数据的过程。

此外,GJSON 还与 SJSONJJ 命令行工具配合使用,分别提供了修改 JSON 数据和命令行交互功能,进一步增加了开发者操作 JSON 的灵活性。

运行以下命令来安装:

下面是一个简单的使用例子,展示了如何从 JSON 字符串中检索特定字段的值:

GJSON 目前是一个活跃的开源项目,它的优势不仅在于其简单、高效的 API,而且因为它为许多工作和项目节约了大量的时间和劳动。由于其卓越的性能和易用性,GJSON 已经被多家知名公司和许多个人项目采用。

以下是该项目 Star 趋势图(代表项目的活跃程度):

更多项目详情请查看如下链接。

开源项目地址:https://github.com/tidwall/gjson

开源项目作者:tidwall

开源协议:MIT License

以下是参与项目建设的所有成员:

关注我们,一起探索有意思的开源项目。

程序员都应该了解的一种数据格式之 JSON

作者 | 猪哥

责编 | maozz

JSON的诞生原因是因为XML整合到HTML中各个浏览器实现的细节不尽相同,所以道格拉斯·克罗克福特(Douglas Crockford) 和 奇普·莫宁斯达(Chip Morningstar)一起从JS的数据类型中提取了一个子集,作为新的数据交换格式,因为主流的浏览器使用了通用的JavaScript引擎组件,所以在解析这种新数据格式时就不存在兼容性问题,于是他们将这种数据格式命名为 “JavaScript Object Notation”,缩写为 JSON,由此JSON便诞生了!

今天我们来学习一下JSON的结构形式、数据类型、使用场景以及注意事项吧!

JSON格式

上面我们知道JSON是从JavaScript的数据类型中提取出来的子集,那JSON有几种结构形式呢?又有哪些数据类型呢?他们又分别对应着JavaScript中的哪些数据类型呢?

JSON的2种结构形式,键值对形式和数组形式。

举了一个JSON的实例,就是键值对形式的,如下:

{

\”person\”: {

\”name\”: \”pig\”,

\”age\”: \”18\”,

\”sex\”: \”man\”,

\”hometown\”: {

\”province\”: \”江西省\”,

\”city\”: \”抚州市\”,

\”county\”: \”崇仁县\”

}

}

}

这种结构的JSON数据规则是:一个无序的“‘名称/值’对”集合。一个对象以 {左括号 开始, }右括号 结束。每个“名称”后跟一个 :冒号 ;“‘名称/值’ 对”之间使用 ,逗号 分隔。

因为大多数的时候大家用的JSON可能都是上面那种key-value形式,所以很多人在讲解JSON的时候总是会忽略数组形式,这一点是需要注意的。

那JSON的数组形式是怎么样的呢?举一个实例吧!

[\”pig\”, 18, \”man\”, \”江西省抚州市崇仁县\”]

数组形式的JSON数据就是值(value)的有序集合。一个数组以 [左中括号 开始, ]右中括号 结束。值之间使用 ,逗号 分隔。

JOSN的6种数据类型

上面两种JSON形式内部都是包含value的,那JSON的value到底有哪些类型,而且上期我们说JSON其实就是从Js数据格式中提取了一个子集,那具体有哪几种数据类型呢?

  1. string:字符串,必须要用双引号引起来。

  2. number:数值,与JavaScript的number一致,整数(不使用小数点或指数计数法)最多为 15 位,小数的最大位数是 17。

  3. object:JavaScript的对象形式,{ key:value }表示方式,可嵌套。

  4. array:数组,JavaScript的Array表示方式[ value ],可嵌套。

  5. true/false:布尔类型,JavaScript的boolean类型。

  6. :空值,JavaScript的。

以上数据形式图片来源JSON官方文档:http://www.json.org/json-zh.html

JSON使用场景

介绍完JSON的数据格式,那我们来看看JSON在企业中使用的比较多的场景。

接口返回数据和序列化。JSON用的最多的地方莫过于Web了,现在的数据接口基本上都是返回的JSON,具体细化的场景有:

  1. Ajxa异步访问数据

  2. RPC远程调用

  3. 前后端分离后端返回的数据

  4. 开放API,如百度、高德等一些开放接口

  5. 企业间合作接口

这种API接口一般都会提供一个接口文档,说明接口的入参、出参等,

一般的接口返回数据都会封装成JSON格式,比如类似下面这种

{

\”code\”: 1,

\”msg\”: \”success\”,

\”data\”: {

\”name\”: \”pig\”,

\”age\”: \”18\”,

\”sex\”: \”man\”,

\”hometown\”: {

\”province\”: \”江西省\”,

\”city\”: \”抚州市\”,

\”county\”: \”崇仁县\”

}

}

}

程序在运行时所有的变量都是保存在内存当中的,如果出现程序重启或者机器宕机的情况,那这些数据就丢失了。一般情况运行时变量并不是那么重要丢了就丢了,但有些内存中的数据是需要保存起来供下次程序或者其他程序使用。

保存内存中的数据要么保存在数据库,要么保存直接到文件中,而将内存中的数据变成可保存或可传输的数据的过程叫做序列化,在Python中叫pickling,在其他语言中也被称之为serialization,marshalling,flattening等等,都是一个意思。

正常的序列化是将编程语言中的对象直接转成可保存或可传输的,这样会保存对象的类型信息,而JSON序列化则不会保留对象类型!

为了让大家更直观的感受区别,猪哥用代码做一个测试,大家一目了然

  1. Python对象直接序列化会保存class信息,下次使用loads加载到内存时直接变成Python对象。

  2. JSON对象序列化只保存属性数据,不保留class信息,下次使用loads加载到内存可以直接转成dict对象,当然也可以转为Person对象,但是需要写辅助方法。

对于JSON序列化不能保存class信息的特点,那JSON序列化还有什么用?答案是当然有用,对于不同编程语言序列化读取有用,比如:我用Python爬取数据然后转成对象,现在我需要将它序列化磁盘,然后使用Java语言读取这份数据,这个时候由于跨语言数据类型不同,所以就需要用到JSON序列化。

存在即合理,两种序列化可根据需求自行选择!

最后就是生成Token和配置文件

首先声明Token的形式多种多样,有JSON、字符串、数字等等,只要能满足需求即可,没有规定用哪种形式。

JSON格式的Token最有代表性的莫过于JWT(JSON Web Tokens)。

随着技术的发展,分布式web应用的普及,通过Session管理用户登录状态成本越来越高,因此慢慢发展成为Token的方式做登录身份校验,然后通过Token去取Redis中的缓存的用户信息,随着之后JWT的出现,校验方式更加简单便捷化,无需通过Redis缓存,而是直接根据Token取出保存的用户信息,以及对Token可用性校验,单点登录更为简单。

使用JWT做过app的登录系统,大概的流程就是:

  1. 用户输入用户名密码

  2. app请求登录中心验证用户名密码

  3. 如果验证通过则生成一个Token,其中Token中包含:

  4. 用户的uid、Token过期时间、过期延期时间等,然后返回给app

  5. app获得Token,保存在cookie中,下次请求其他服务则带上

  6. 其他服务获取到Token之后调用登录中心接口验证

  7. 验证通过则响应

JWT登录认证有哪些优势:

  1. 性能好:服务器不需要保存大量的session

  2. 单点登录(登录一个应用,同一个企业的其他应用都可以访问):使用JWT做一个登录中心基本搞定,很容易实现。

  3. 兼容性好:支持移动设备,支持跨程序调用,Cookie 是不允许垮域访问的,而 Token 则不存在这个问题。

  4. 安全性好:因为有签名,所以JWT可以防止被篡改。更多JWT相关知识自行在网上学习,本文不过多介绍!

说实话JSON作为配置文件使用场景并不多,最具代表性的就是npm的package.json包管理配置文件了,下面就是一个npm的package.json配置文件内容。

{

\”name\”: \”server\”, //项目名称

\”version\”: \”0.0.0\”,

\”private\”: true,

\”main\”: \”server.js\”, //项目入口地址,即执行npm后会执行的项目

\”scripts\”: {

\”start\”: \”node ./bin/www\” ///scripts指定了运行脚本命令的npm命令行缩写

},

\”dependencies\”: {

\”cookie-parser\”: \”~1.4.3\”, //指定项目开发所需的模块

\”debug\”: \”~2.6.9\”,

\”express\”: \”~4.16.0\”,

\”http-errors\”: \”~1.6.2\”,

\”jade\”: \”~1.11.0\”,

\”morgan\”: \”~1.9.0\”

}

}

但其实JSON并不合适做配置文件,因为它不能写注释、作为配置文件的可读性差等原因。

配置文件的格式有很多种如:toml、yaml、xml、ini等,目前很多地方开始使用yaml作为配置文件格式。

JSON在Python中的使用

最后我们来看看Python中操作JSON的常用方法有哪些,在Python中操作JSON时需要引入json标准库。

import json

类型转换

Python类型转JSON:json.dump

# 1、Python的dict类型转JSON

person_dict = {\’name\’: \’pig\’, \’age\’: 18, \’sex\’: \’man\’, \’hometown\’: \’江西抚州\’}

# indent参数为缩进空格数

person_dict_json = json.dumps(person_dict, indent=4)

print(person_dict_json, \’\\n\’)

# 2、Python的列表类型转JSON

person_list = [\’pig\’, 18, \’man\’, \’江西抚州\’]

person_list_json = json.dumps(person_list)

print(person_list_json, \’\\n\’)

# 3、Python的对象类型转JSON

person_obj = Person(\’pig\’, 18, \’man\’, \’江西抚州\’)

# 中间的匿名函数是获得对象所有属性的字典形式

person_obj_json = json.dumps(person_obj, default=lambda obj: obj.__dict__, indent=4)

print(person_obj_json, \’\\n\’)

执行结果:

JSON转Python类型:json.loads

# 4、JSON转Python的dict类型

person_json = \'{ \”name\”: \”pig\”,\”age\”: 18, \”sex\”: \”man\”, \”hometown\”: \”江西抚州\”}\’

person_json_dict = json.loads(person_json)

print(type(person_json_dict), \’\\n\’)

# 5、JSON转Python的列表类型

person_json2 = \'[\”pig\”, 18, \”man\”, \”江西抚州\”]\’

person_json_list = json.loads(person_json2)

print(type(person_json_list), \’\\n\’)

# 6、JSON转Python的自定义对象类型

person_json = \'{ \”name\”: \”pig\”,\”age\”: 18, \”sex\”: \”man\”, \”hometown\”: \”江西抚州\”}\’

# object_hook参数是将dict对象转成自定义对象

person_json_obj = json.loads(person_json, object_hook=lambda d: Person(d[\’name\’], d[\’age\’], d[\’sex\’], d[\’hometown\’]))

print(type(person_json_obj), \’\\n\’)

执行结果如下:

对应的数据类型

上面我们演示了Python类型与JSON的相互转换,最开始的时候我们讲过JSON有6种数据类型,那这6种数据类型分别对应Python中的哪些数据类型呢?

需要注意的点

JSON的键名和字符串都必须使用双引号引起来,而Python中单引号也可以表示为字符串,所以这是个比较容易犯的错误!

Python类型与JSON相互转换的时候到底是用load/dump还是用loads\\dumps?

  • 他们之间有什么区别?

  • 什么时候该加s什么时候不该加s?

这个我们可以通过查看源码找到答案:

不加s的方法入参多了一个fp表示filepath,最后多了一个写入文件的操作。

所以我们在记忆的时候可以这样记忆:

加s表示转成字符串(str),不加s表示转成文件。

Python自定义对象与JSON相互转换的时候需要辅助方法来指明属性与键名的对应关系,如果不指定一个方法则会抛出异常!

相信有些看的仔细的同学会好奇上面使用json.dumps方法将Python类型转JSON的时候,如果出现中文,则会出现:

\\u6c5f\\u897f\\u629a\\u5dde

这种东西,这是为什么呢?

原因是:Python 3中的json在做dumps操作时,会将中文转换成unicode编码,并以16进制方式存储,而并不是UTF-8格式!

总结

今天我们学习了JSON的2种形式,切记JSON还有[…]这种形式的。

学习了JSON的6种数据类型他们分别对于Python中的哪些类型。

了解了JSON的一些使用场景以及实际的例子。

还学习了在Python中如何使用JSON以及需要注意的事项。

一个JSON知识点却分两篇长文(近万字)来讲,其重要性不言而喻。因为不管你是做爬虫、还是做数据分析、web、甚至前端、测试、运维,JSON都是你必须要掌握的一个知识点

本文为作者投稿,版权归作者个人所有。

本文作者及来源:Renderbus瑞云渲染农场https://www.renderbus.com

点赞 0
收藏 0

文章为作者独立观点不代本网立场,未经允许不得转载。