简介
jackson支持java和Kotlin、Scala等语言,支持JSON及JSON以外的多种格式转换。
是Spring家族默认的JSON、XML解析器。
语法特点:纵观整个Jackson,它更多的是使用抽象类而非接口。
1 | <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core --> |
三大核心模块
jackson-core
: Streaming流处理模块,定义底层处理流API:JsonPaser和JsonGenerator等,并包含特定于json的实现。jackson-annotations
:Annotations标准注解模块,包含标准的Jackson注解。jackson-databind
:Databind数据绑定模块,在streaming包上实现数据绑定(和对象序列化)支持;它依赖于上面的两个模块,也是Jackson的高层API(如ObjectMapper)所在的模块。实际开发中,只用到Databind数据绑定模块
扩展模块
通过扩展模块,让Jackson databind
包(ObjectMapper / ObjectReader / ObjectWriter
)能够顺利读写/转换扩展的类型。
- 利用Jackson插件模块(
ObjectMapper.registerModule()
), - 添加序列化器和反序列化器
- 最终支持各种常用Java库数据类型。
数据类型模块datatype
官方维护的扩展模块
* groupId为:`<groupId>com.fasterxml.jackson.datatype</groupId>`
- version和官方主版本号相对应
非官方直接维护的扩展模块
* groupId不确定,版本号与官方主版本无关。比如:
- jackson-datatype-commons-lang3:支持
Apache Commons Lang v3
里面的一些类型 - jackson-datatype-money:支持
javax.money
- jackson-datatype-json-lib:对久远的
json-lib
这个库的支持
- jackson-datatype-commons-lang3:支持
数据格式模块dataformat
支持JSON之外的数据格式,大多数只是实现streaming API抽象,以便数据绑定组件可以按原样使用。
- 官方维护的扩展模块
- groupId为:
<groupId>com.fasterxml.jackson.dataformat</groupId>
- version和官方主版本号相对应。
- Avro/CBOR/Ion/Protobuf/Smile(binary JSON) :二进制格式,artifactId为:
<artifactId>jackson-dataformat-[FORMAT]</artifactId>
- CSV/Properties/XML/YAML等文本格式。
- groupId为:
- 非官方直接维护的扩展模块。
支持Kotlin和Scala的依赖
- groupId为:
<groupId>com.fasterxml.jackson.module</groupId>
- version和官方主版本号相对应。
- jackson-module-kotlin:处理kotlin源生类型
- jackson-module-scala_[scala版本号]:处理scala源生类型
支持移动端的依赖
jackson.jr,一个轻量级的更简单、更小的库。
仅依赖jackson-core
,并不依赖于annotation和databind。
- Jackson三大核心模块大小:343KB(core)+ 66KB(annotation)+ 1.4M(databind)。
- Jackson jr大小:96KB(jr) + 343KB(core)
1 | <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.jr/jackson-jr-objects --> |
JSON的三种处理方式
方式 | 描述 | 隶属包 |
---|---|---|
流式API | 读/写性能最好、开销最低、 速度最快; 其它2者都基于它实现。 | jackson-core |
树模型 | 类似于XML的DOM解析,层层嵌套。是最灵活的方式 | jackson-core |
数据绑定 | JSON和POJO相互转换,是使用最方便的方式。使用最多。 | jackson-databind |
- 流式API,读取和写入JSON内容作为离散事件
- 读数据:
org.codehaus.jackson.JsonParser
- 写数据:
org.codehaus.jackson.JsonGenerator
- 流式,指的是IO流,因此具有最低的开销。
- 使用流式API读写JSON的方式,使用的均是增量模式(每个部分一个一个地往上增加,类似于垒砖)
- 流式API里很重要的一个抽象概念JsonToken:每一部分都是一个独立的Token(有不同类型的Token),最终被“拼凑”起来就是一个JSON。
- 读数据:
- 树模型,JSON文件在内存里以树形式表示
org.codehaus.jackson.map.ObjectMapper
生成树- 树组成
JsonNode
节点集
- 数据绑定,JSON和POJO相互转换
- 简单数据绑定,是指从Java Map、List、String、Numbers、Boolean和空值进行转换
- 完整数据绑定,是指从任何Java bean类型 (及上文所述的”简单”类型) 进行转换
- 使用最方便的方式
流式API
实际是i/o流读写。隶属于jackson-core包。
写操作:JsonGenerator
运行案例
1 | // ----------基本实现------ |
try-with-resources:jdk1.7引入,一种语法糖,主要是替代了 try-catch-finally/try-finaly中的finally ,但是在编译的时候,还是会转回 try-catch-finally/try-finaly。
要求:在 try-with-resources 声明中定义的变量,要实现AutoCloseable 接口。
这样在系统可以自动调用它们的close方法,从而替代了finally中关闭资源的功能。
注意点:try-with-resources之后,又进行追加的catch 和 finally 中的代码,会在try-with-resources自动资源关闭之后才运行。
1 | // try-finaly |
相关类
WriterBasedJsonGenerator
:基于:java.io.Writer
处理字符编码(使用Writer输出JSON)- 因为UTF-8编码基本标准化了,因此Jackson内部也提供了
SegmentedStringWriter/UTF8Writer
来简化操作
- 因为UTF-8编码基本标准化了,因此Jackson内部也提供了
UTF8JsonGenerator
:基于OutputStream + UTF-8处理字符编码(默认指定使用UTF-8编码把字节变为字符)
json实现
key,可以独立存在(无需value),但value不能独立存在{"name":"want","age":23,"school"}
。生成独立key方法如下:
- jsonGenerator.writeFieldName(“school”);
- jsonGenerator.writeFieldId(123);只能是数字,且本质还是用writeFieldName来实现。
1 | // 独立存在的key,放到最后,因为碰到独立key,json就终止了 |
value,JSON中取值类型只能如下6种,但是Java中数据类型更丰富,需要JsonGenerator进行映射。
graph LR A(java数据类型) --JsonGenerator--> B(JSON数据格式)
字符串
1 | // key-value分开写 |
Base64编码
1 | jsonGenerator.writeFieldName("base64"); |
文本原样输出
1 | jsonGenerator.writeFieldName("love1"); |
数字
1 | jsonGenerator.writeFieldName("age"); |
布尔
1 | jsonGenerator.writeFieldName("isMan"); |
数组
1 | // ------key-value分开写法------ |
对象
1 | // ------key-value分开写法------ |
POJO实体类
1 | // User实体类转json |
嵌套实体类,其实是个树结构转JSON,但core模块没有提供树模型TreeNode的实现
实现方式:
- writeTree()
- setCodec()解码器
1 | class UserTreeNode implements TreeNode { |
null
1 | jsonGenerator.writeNullField("weight"); |
树模型
writeTree()