Gson、FastJson、Jackson都是第三方序列化/反序列化 JSON格式的 Java库。JSON 是一种文本形式的数据交换格式,它比XML更轻量、比二进制容易阅读和编写,调式也更加方便。
一、Gson
介绍
Gson是Google提供的用来在Java对象和JSON数据之间进行映射的Java类库。Gson 最初是为在 Google 内部使用而创建的,后面进行了开源,Gson可以将一个Json字符转成一个Java对象,或者将一个Java转化为Json字符串。
关于性能和扩展性
以下是我们在运行许多其他东西以及测试的台式机(双 opteron、8GB RAM、64 位 Ubuntu)上获得的一些指标。您可以使用PerformanceTest类重新运行这些测试。
- 字符串:超过 25MB 的反序列化字符串没有任何问题(参见PerformanceTest 中的disabled_testStringDeserializationPerformance方法)
- 大集合:
- 序列化了 140 万个对象的集合(参见PerformanceTest 中的disabled_testLargeCollectionSerialization方法)
- 反序列化87000个对象的集合(见disabled_testLargeCollectionDeserialization在PerformanceTest)
- Gson 1.4 将字节数组和集合的反序列化限制从 80KB 提高到 11MB 以上。
注意:删除disabled_前缀以运行这些测试。我们使用这个前缀来防止每次运行 junit 测试时运行这些测试。
使用 Gson
要使用的主要类是Gson,您可以通过调用 new Gson() 来创建它。还有一个类GsonBuilder可用于创建具有各种设置(如版本控制等)的 Gson 实例。
Gson 实例在调用 Json 操作时不维护任何状态。因此,您可以自由地为多个 Json 序列化和反序列化操作重用同一个对象。
Maven:
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.9</version>
</dependency>
//创建方式一
Gson gson = new gson();
User obj= new User();
String json = gson.toJson(obj); //序列化user对象
User obj2 = gson.fromJson(json, User.class); //反序列化对象</code></pre>
//创建方式二
Gson gson = new GsonBuilder()
//序列化null
.serializeNulls()
// 设置日期时间格式,另有2个重载方法
// 在序列化和反序化时均生效
.setDateFormat("yyyy-MM-dd")
// 禁此序列化内部类
.disableInnerClassSerialization()
//生成不可执行的Json(多了 )]}' 这4个字符)
.generateNonExecutableJson()
//禁止转义html标签
.disableHtmlEscaping()
//格式化输出
.setPrettyPrinting()
.create();
User obj= new User();
String json = gson.toJson(obj); //序列化user对象
User obj2 = gson.fromJson(json, User.class); //反序列化对象
使用对象序列化优点
- 使用私有字段非常好(并推荐)
- 不需要使用任何注释来指示要包含的字段以进行序列化和反序列化。默认情况下包含当前类(以及所有超类)中的所有字段。
- 如果字段被标记为transient,(默认情况下)它会被忽略并且不包含在 JSON 序列化或反序列化中。
- 此实现正确处理空值
- 序列化时,从输出中跳过空字段
- 反序列化时,JSON 中缺少条目导致将对象中的相应字段设置为 null
- 如果字段是synthetic的,则它会被忽略并且不包括在 JSON 序列化或反序列化中
- 内部类、匿名类和本地类中对应于外部类的字段被忽略,不包括在序列化或反序列化中
更多关于Gson的内容查看官网:https://sites.google.com/site/gson/gson-user-guide
二、FastJson
介绍
fastjson是阿里巴巴的开源JSON解析库,它可以解析JSON格式的字符串,支持将Java Bean序列化为JSON字符串,也可以从JSON字符串反序列化到JavaBean。
Maven:
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>x.x.x</version>
</dependency>
其中 x.x.x 是版本号,根据需要使用特定版本,建议使用最新版本。
优点
1.速度快
fastjson相对其他JSON库的特点是快,从2011年fastjson发布1.1.x版本之后,其性能从未被其他Java实现的JSON库超越。
2.使用广泛
fastjson在阿里巴巴大规模使用,在数万台服务器上部署,fastjson在业界被广泛接受。在2012年被开源中国评选为最受欢迎的国产开源软件之一。
3.测试完备
fastjson有非常多的testcase,在1.2.11版本中,testcase超过3321个。每次发布都会进行回归测试,保证质量稳定。
使用
User obj= new User();
//序列化对象
String json =JSON.toJSONString(obj);
//反序列化对象
User user=JSON.parseObject(json,User.class);
//反序列化集合方式一
List<User> res= JSON.parseArray(json,User.class);
//反序列化集合方式二
List<User> res6= JSON.parseObject(json,new TypeReference<List<User>>(){});
更多使用方式参考官方文档:https://github.com/alibaba/fastjson/wiki
漏洞
为了解决 在使用fastjson进行序列化的时候,会将子类型抹去,只保留接口(抽象类)的类型,使得反序列化时无法拿到原始类型,因此FastJson引入AutoType即在序列化的时候,把原始类型记录下来。后面带来的漏洞全与引入的AutoType特性有关。具体参看:https://zhuanlan.zhihu.com/p/157211675?from_voters_page=true
三、Jackson
介绍
Jackson是一个简单的基于Java的库,用于将Java对象序列化为JSON,也可以把JSON转换为Java对象,是SpringBoot默认序列化Json库。
SpringBoot提供了 Jackson 的自动配置,spring-boot-starter-json
. 当自动配置好ObjectMapper
后会加载到类路径上。一些配置属性用于自定义 ObjectMapper.
下面表格为可配置项:
枚举类 | 属性 | 值 |
---|---|---|
com.fasterxml.jackson.databind.DeserializationFeature | spring.jackson.deserialization.<feature_name> | true , false |
com.fasterxml.jackson.core.JsonGenerator.Feature | spring.jackson.generator.<feature_name> | true , false |
com.fasterxml.jackson.databind.MapperFeature | spring.jackson.mapper.<feature_name> | true , false |
com.fasterxml.jackson.core.JsonParser.Feature | spring.jackson.parser.<feature_name> | true , false |
com.fasterxml.jackson.databind.SerializationFeature | spring.jackson.serialization.<feature_name> | true , false |
com.fasterxml.jackson.annotation.JsonInclude.Include | spring.jackson.default-property-inclusion | always , non_null , non_absent , non_default , non_empty |
特点
- 易于使用:-Jackson API提供了高级外观,以简化常用使用。
- 无需创建映射:Jackson API为大多数序列化的对象提供了默认映射。
- 性能:Jackson轻便快速,内存占用少,适用于大型对象图或系统。
- 干净的JSON:Jackson创建了简洁的JSON,易于阅读。
- 没有依赖关系:Jackson库除JDK以外不需要任何其他库。
- 开源:Jackson库是开源的,可以免费使用。
注解
反序列化/序列化的过程中操作
@JsonFormat
: 实体类/属性使用的注解,在序列化或者反序列化的时候,指定属性格式化日期/时间。@JsonUnwrapped
: 作用在属性字段或方法上,用来将子JSON对象的属性添加到封闭的JSON对象。- 如果没有@JsonUnwrapped,序列化后将为{"id":111,"name":{"firstName":"张","secondName":"三"}}
- 反之:{"id":111,"firstName":"张","secondName":"三"}
@JsonView
该注解指明属性序列化和反序列时的视图级别(View)
反序列化的过程中操作
@JacksonInject
@JsonAnySetter
@JsonCreator
@JsonSetter
@JsonEnumDefaultValue
序列化的过程中操作
@JsonAnyGetter
@JsonGetter
@JsonPropertyOrder
@JsonRawValue
@JsonValue
@JsonRootName
类型处理
@JsonSubTypes
@JsonTypeId
@JsonTypeInfo
@JsonTypeName
对象引用及标识
@JsonManagedReference
@JsonIdentityInfo
元注释
@JacksonAnnotation
@JacksonAnnotationsInside
官方文档:https://github.com/FasterXML/jackson-annotations/wiki/Jackson-Annotations
使用
ObjectMapper是JSON操作的核心,Jackson的所有JSON操作都是在ObjectMapper中实现。ObjectMapper有多个JSON序列化的方法,可以把JSON字符串保存File、OutputStream等不同的介质中。
基本方法
writeValue(File arg0, Object arg1)//把arg1转成json序列,并保存到arg0文件中。
writeValue(OutputStream arg0, Object arg1)//把arg1转成json序列,并保存到arg0输出流中。
writeValueAsBytes(Object arg0)//把arg0转成json序列,并把结果输出成字节数组。
使用实例
//POJO 转Json
User user=new User();
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(user);
user = mapper.readValue(json, User.class);
//Java集合转JSON
List<User> users = new ArrayList<User>();
users.add(user);
String jsonlist = mapper.writeValueAsString(users);
List<User> readValue = mapper.readValue(jsonList,new TypeReference<List<User>>(){});
总结
性能
把Java对象JSON序列化,Jackson速度最快,在测试中比Gson快接近50%,FastJSON和Gson速度接近。
把JSON反序列化成Java对象,FastJSON、Jackson速度接近,Gson速度稍慢,不过差距很小。
性能方面,Jackson和FastJson差距很小,Jackson是SpringBoot默认的序列化库,也是最稳定的一个,FastJson由于频繁被曝出漏洞且作者没有那么多精力维护,所以默认序列方式还是选择Jackson最好。
参考资料
https://github.com/alibaba/fastjson/wiki
https://sites.google.com/site/gson/gson-user-guide
https://github.com/FasterXML/jackson-annotations/wiki/Jackson-Annotations