使用Jackson生成和解析JSON
参考声明:https://www.pudn.com/news/62eb6e90864d5c73ac50d924.html
Jackson是目前使用非常广泛的JSON生成和解析工具。
Jackson项目主要由三个模块儿组成:
- jackson-core 提供了一套流式API,他不仅自带了JSON的解析器和生成器,还支持扩展数据格式,比如XML、CSV和Protobuf等
- jackson-annotations 提供了处理数据时需要的注解
- jackson-databind 可以将数据和Java对象进行绑定,使用起来更方便、更符合直觉
通常来说,我们提到Jackson的时候,指的就是jackson-databind,他直接依赖了jackson-core和jackson-annotations。我们用Jackson的时候,通常也只是用来处理JSON,其他数据格式可以参考官网进行扩展。
如何引入?
如果你使用Spring Boot开发pngb应用的话,Jackson已经内置在你的项目里了:
Jackson是Spring Boot的默认使用的
如果你在其他情况下使用,可以添加以下依赖(假设使用Gradle构建项目):
查询最新版本可以参照mvnrepository.com
快速开始
学习一个库的最快的方式就是通过实践来感受其作用。下图中的程序用简单的代码说明了如何根据Java对象生成JSON字符串:
ObjectMapper是Jackson中的核心类,他用来完成JSON的读写操作,除了上面的writeValueAsString方法,ObjectMapper还可以通过readValue方法将JSON字符串解析成Java对象。Jackson中的很多特性(Feature)都可以通过ObjectMapper来配置。如果你使用Spring Boot,那么ObjectMapper就已经存在于你的Spring容器中了,当你需要他的时候,只需要通过@AutoWired注入这个对象。
User对象的成员变量的名字和值,都会成为JSON中的属性名称和属性值。你也是可以通过@JsonProperty来更改属性名称的:
我经常将每个成员变量都加上@JsonProperty注解,因为很多情况下他们的命名风格很可能不一样,而且如果对代码进行重构,不会导致对外提供的API变化。
如果你的对象中有个成员变量不需要参与到JSON的处理过程中,可以给他加上@JsonIgnore注解:
同样,也可尝试在User类上加注解@JsonIgnoreProperties,实现的效果和上面是相同的:
使用Setter和Getter
对于User对象,很多时候我们会把成员变量设置为private,利用getter和setter来操作成员,需要注意是,如果你用了setter和getter,Jackson会以getter的名字来决定JSON的属性名,如图所示:
name成员对应的属性名变成了nameName
@JsonProperty同样也可以使用在getNameName方法上,来指定属性名。
实际上,Jackson是通过以下顺序来检测JSON的属性名的:
- public的成员变量
- public的getter方法
- 所有作用域的setter方法
这个顺序和规则是可以控制的,使用@JsonAutoDetect注解,放到User类上,可以控制需不需要自动检测private和protected的成员变量,可以控制private和protected的getter能否被自动检测到等等。然而,何必搞得这么复杂呢?为什么不搞个简单可依赖的实践呢?
我是这样做的,忽略掉所有的getter和setter的自动检测,只依赖成员变量。除了在每个类上都加上@JsonAutoDetect注解,还可以配置ObjectMapper:
这样不管是成员变量是public、private还是protected,都可以自动检测。如果用了Spring Boot,可以添加如下设置:
这样做的好处就是,你只需要关心成员变量就行,出了问题不需要再去寻找getter和setter方法了,而且对于使用了Lombok的项目,你不用再担心自动生成的getter和setter会导致JSON属性名的变化。还有,boolean类型成员变量的getter和setter的命名,你和IDE还有Jackson的认知可能还不太一致,有可能会出错(比如:问题1、问题2)。
内嵌JSON对象或者JSON数组
内嵌JSON对象或者JSON数组,只需要把成员变量的类型改了就行:
手动操作JSON
有的时候你的JSON内部会比较简单,或者比较多变,这个时候就需要手动生成。ObjectMapper有一个createObjectNode方法,会创建一个新的JSON对象,你可以通过put方法来往其中添加数据:
添加数组的时候,可能跟添加字符串或者证书的不太一样,putArray调用完毕自后,会返回一个ArrayNode对象,在这个对象中添加数组内容会反应到最终的JSON串中。
Jackson的API非常丰富,上面做说的这些东西只能算是满足了常见的需求,我之后再写点文章详细说说。