Java常用的JSON序列化与反序列化工具实践

京东云开发者
• 阅读 343

JSON简介:

JSON(Java Script Object Notation)是一种轻量级的数据交换格式,通常用于在不同系统之间传输数据。它基于 JavaScript 对象语法,但已成为一种独立于语言的格式。JSON 数据以键值对的形式组织,易于阅读和编写。

为什么要使用 JSON?

1.简单易用:JSON的语法简单,易于理解和编写,可以快速地进行数据交换。

2.跨平台支持:JSON可以被多种编程语言解析和生成,可以在不同的平台和语言之间进行数据交换和传输。

3.数据交换格式:JSON是一种标准的数据交换格式,可以在Web应用程序中广泛使用,如前后端数据交互、API接口数据传输等。

4.轻量级:JSON的数据格式轻量级,传输数据时占用带宽较小,可以提高数据传输速度。

5.易于扩展:JSON的数据结构灵活,支持嵌套对象和数组等复杂的数据结构,便于扩展和使用。

6.安全性:JSON数据格式是一种纯文本格式,不包含可执行代码,不会执行恶意代码,因此具有较高的安全性。

什么时候会使用 JSON?

1.前后端数据传输:当Web应用程序需要进行前后端数据传输时,可以使用JSON格式来传输数据,以便前后端之间进行数据交互。

2.API接口数据传输:当使用API接口进行数据传输时,可以使用JSON格式来传输数据,以便多个系统之间进行数据交互。

3.存储数据:当需要存储数据时,可以使用JSON格式来存储数据,以便后续的读取、修改和删除等操作。

4.日志记录:当需要记录日志时,可以使用JSON格式来记录日志信息,以便后续的分析和查询。

5.配置文件:当需要存储配置文件时,可以使用JSON格式来存储配置信息,以便后续的读取和修改操作。



JSON序列化与反序列化实践。

java中比较常用的JSON工具 fastjson,fastjson2,jackson,gson。实践的内容是新增字段的场景,各个工具的兼容性以及不同工具间的兼容性。

前置条件

各个JSON工具的版本号:

fastjson

 <dependency>
     <groupId>com.alibaba</groupId>
     <artifactId>fastjson</artifactId>
     <version>1.2.83-jdsec.rc1</version>
 </dependency>

fastjson2

<dependency>
    <groupId>com.alibaba.fastjson2</groupId>
    <artifactId>fastjson2</artifactId>
    <version>2.0.48</version>
</dependency>

jackson

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.7.9</version>
</dependency>

gson

<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.8.8</version>
</dependency>

实体类:

现在三个类 Person 、OldFamily、Family三个类,Family是在OldFamily中增加了新属性oldPerson。主要是为了模拟数据处理时,新老数据的兼容问题。

@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class Person {
    private String name;
    private int age;
    private int sex;
}
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Family {
    private Person yongPerson;
    private Person oldPerson;
    private List<Person> persons;
}
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class OldFamily {

    private Person yongPerson;

    private List<Person> persons;
}

fastjson序列化与反序列化



Java常用的JSON序列化与反序列化工具实践



通过程序运行结果,可以观察到在Family序列化结果中,persons属性中的第三个person实例是oldPerson实例的引用,而yongPerson属性的值是persons属性中下标为0的实例的引用。这已经不是标准的JSON格式,而是fastjson的特性。当增加oldPerson属性后,Family序列化的结果在反序列化为OldFamily对象实例时,persons属性中有一个person实例为空。虽然反序列化不会报错,但程序将无法得到预期的结果。



为解决这个问题,fastjson在序列化时是默认的顺序是按照属性字段的字母顺序排序。你也可以通过注解的方式指定顺序,将新增加的属性放到orders的最后。

@JSONType(orders={"yongPerson", "persons", "oldPerson"})
public class Family {

    private Person yongPerson;

    private List<Person> persons;

    private Person oldPerson;

}



Java常用的JSON序列化与反序列化工具实践



通过序列化结果可以看到oldPerson这个新增加的属性已经引用了persons属性中下标为2的实例。反序列化之后的OldFamily对象persons属性中的三个实例都有值,不会再有null值。程序还可以确保正确运行。



fastjson1.X 可以通过SerializerFeature参数来输出标准JSON格式

public static String toJSONString(Object object, SerializerFeature... features) {
    return toJSONString(object, DEFAULT_GENERATE_FEATURE, features);
}



Java常用的JSON序列化与反序列化工具实践



通过程序运行结果可以看出,当指定序列化参数SerializerFeature.DisableCircularReferenceDetect时,是以标准的Json格式输出。



fasJson2序列化与反序列化

在fastjson2中,将对象序列化为JSON格式时,默认情况下就是标准的JSON格式。你可以通过设置com.alibaba.fastjson2.JSONWriter.Feature参数值为`JSONWriter.Feature.ReferenceDetection



Java常用的JSON序列化与反序列化工具实践



即使用标准的JSON格式作为默认序列化方式是合理的。非标准化的方式应当需要特殊指定。在使用fastjson2版本2.0.26时,当设置com.alibaba.fastjson2.JSONWriter.Feature参数值为JSONWriter.Feature.ReferenceDetection时,会导致序列化和反序列化成Family实例结果得不到预期结果。

而在反序列化为OldFamily实例结果正确是因为没有oldPerson属性。



然而,在最新的2.0.48版本中,可以正常进行序列化和反序列化。以下是fastjson2的2.0.48版本的运营结果



Java常用的JSON序列化与反序列化工具实践



gson序列化与反序列化

在gson中,默认情况下,当在Fimaly类中新增了oldPerson属性时,Fimaly的序列化结果可以正确地反序列化成OldFimaly类的实例。



Java常用的JSON序列化与反序列化工具实践



Jackson序列化与反序列化

Jackson默认情况下,当在Fimaly类中新增了oldPerson属性时,Fimaly类的序列化结果无法正确反序列化成OldFimaly类实例。是因为Jackson在默认情况下进行反序列化时,要求所有属性都必须存在才能正确反序列化。



Java常用的JSON序列化与反序列化工具实践





解决方案1 通过代码设置ObjectMapper中DeserializationFeature的属性

objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);



Java常用的JSON序列化与反序列化工具实践



解决方案2 在类上使用

com.fasterxml.jackson.annotation.JsonIgnoreProperties(ignoreUnknown = true)



Java常用的JSON序列化与反序列化工具实践





Java常用的JSON序列化与反序列化工具实践



在使用jackson进行序列化和反序列化时,最好指定不进行属性检测。否则,在类新增属性的情况下就无法实现兼容。

fastjson默认序列化fastjson2反序列化



Java常用的JSON序列化与反序列化工具实践



通过测试结果可以看出,fastjson2可以反序列化出fastjson默认序列化的json结果,说明了fastjson2兼容了fastjson。毕竟都是阿里出品。

fastjson2序列化fastjson反序列化



Java常用的JSON序列化与反序列化工具实践



通过测试结果可以看出,fastjson2可以反序列化出fastjson默认序列化的json结果,说明了fastjson2兼容了fastjson。毕竟都是阿里出品。



fastjson默认序列化 jackson反序列化



Java常用的JSON序列化与反序列化工具实践



通过结果可以看出,使用jackson进行反序列化时,没有指定了DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES为false,那么默认值为true,会把“$ref”作为属性进行检测,无论是OldPerson还是Person都没有此属性。会抛出异常。





Java常用的JSON序列化与反序列化工具实践



通过结果可以看出,使用jackson进行反序列化时,指定了DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES为false没有报异常,但是person对象是以属性的默认值实例化的,没有得到想要的结果。

fastjson默认序列化gson反序列化



Java常用的JSON序列化与反序列化工具实践



通过结果可以看出,使用gson进行反序列化时没有报异常,但是person对象是以属性的默认值实例化的,没有得到预期结果。

总结:



1.使用fastjson时,默认的序列化方式会对于具有相同对象的多个引用,除了第一个会以标准的JSON文本输出,其他引用会以“$ref”的方式输出文本。为了以标准的JSON格式输出文本,可以使用SerializerFeature.DisableCircularReferenceDetect参数。而fastjson2的默认序列化输出是标准的JSON格式,若需要具有fastjson默认序列化特性的场景,可以指定com.alibaba.fastjson2.JSONWriter.Feature参数值为JSONWriter.Feature.ReferenceDetection

2.在使用fastjson或者fastjson2的特性,具有相同对象的多个引用,除了第一个会以标准的JSON文本输出,其他引用会以“$ref”的方式输出文本。在新增类属性字段的情况下,一定要把新增的属性放到最后序列化,确保在反序列化成没有新增属性类实例时,得不到预期结果造成线上事故。

3.fastjson和fastjson2在一定程度上是兼容的,但也存在版本差异和Bug,因此在使用时需要进行充分的测试验证。另外,gson、jackson和fastjson2的默认序列化方式也是标准JSON格式。对于jackson,若要在反序列化时兼容不存在的属性的JSON文本成为对象实例,需要设定DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES为false。

4.在使用JSON序列化工具时,需要注意每个工具的特点,尤其是在使用各自具有的特性时,要留意兼容性问题。在进行JSON工具版本升级时,也要进行充分的测试验证,确保有单元测试来保证质量。

5.若作为与外部系统交互的JSON格式数据,需要以标准化的数据格式进行存储或传输。

6.以上内容仅代表个人观点和一小部分实践,欢迎大家一起探讨。

作者:京东物流 吴宪彬

来源:京东云开发者社区

点赞
收藏
评论区
推荐文章
DejiaVu DejiaVu
3年前
你不知道的JSON Schema
1、JSON?JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。具有简洁、可读性高、支持广泛的特点。下面我们用JSON描述了一个商品的基本信息,包含了JSON的一些基本数据的类型。json{"productId":1,"
Aidan075 Aidan075
3年前
一篇长文带你在python里玩转Json数据
↑一个宝藏公众号,长的好看的人都关注了Json简介Json(JavaScriptObjectNotation)很多网站都会用到Json格式来进行数据的传输和交换,就像上篇我提到的,它们返回的数据都是Json格式的。这因为Json是一种轻量级的数据交换格式,具有数据格式简单,读写方便易懂等很多优点。用它来进行前后端的数据传输,大
Bill78 Bill78
3年前
Python中JSON的基本使用_Just do it !
JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。Python3中可以使用json模块来对JSON数据进行编解码,它主要提供了四个方法:dumps、dump、loads、load。dump和dumpsdump和dumps对python对象进行序列化。将一个Python对象
Wesley13 Wesley13
3年前
JSON的简单认识
1前言JSON(JavaScript Object Notation):JavaScript对象表示法。其是一种轻量级的数据交换格式,简洁和清晰的层次结构使得其成为理想的数据交换语言。易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。通常用于与服务端交换数据。如心知天气服务器
Stella981 Stella981
3年前
Go的json解析:Marshal与Unmarshal
简介Json(JavascriptObjectNanotation)是一种数据交换格式,常用于前后端数据传输。任意一端将数据转换成json字符串,另一端再将该字符串解析成相应的数据结构,如string类型,strcut对象等。go语言本身为我们提供了json的工具包”encoding/json”。更多的使用方式,可以参考:https:
Easter79 Easter79
3年前
Swifter.Json 可能是 .Net 平台迄今为止性能最佳的 Json 序列化库【开源】
Json简介Json(JavaScriptObjectNotation)是一种轻量级的数据交换格式。它作为目前最欢迎的数据交换格式,也是各大开源贡献者的必争之地,如:阿里爸爸的fastjson(java),腾讯的rapidjson(c)等。但.Net却没有得到大厂的青睐,在Swifter.Json之前.Net的J
Stella981 Stella981
3年前
PHP serialize & JSON 解析
对于JSON(JavaScriptObjectNotation)大家应该不陌生,它是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLanguage(https://www.oschina.net/action/GoToLink?urlhttp%3A%2F%2Fwww.cro
Stella981 Stella981
3年前
Python and JSON
什么是json:JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLanguage,StandardECMA2623rdEditionDecember1999的一个子集。JSON采用完全独立于语言的
Wesley13 Wesley13
3年前
JSON
JSON(JavaScriptObjectNotation,js对象表示法)  是存储和交换文本信息的语法,类似 XMLJSON的文件类型是“.json”优点:    比XML更小、更快,更容易解析      是轻量级的文本数据交换格式   结构清晰简洁,易于阅读和编写,也易于机器的解析和生成,可以有效的提
Stella981 Stella981
3年前
Golang 入门系列(九) 如何读取YAML,JSON,INI等配置文件
实际项目中,读取相关的系统配置文件是很常见的事情。今天就来说一说,Golang是如何读取YAML,JSON,INI等配置文件的。1\.json使用JSON应该比较熟悉,它是一种轻量级的数据交换格式。层次结构简洁清晰,易于阅读和编写,同时也易于机器解析和生成。  1.创建conf.json:{