使用Jackson生成和解析JSON

Jackson是目前使用非常广泛的JSON生成和解析工具。

Jackson项目主要由三个模块儿组成:

  • jackson-core 提供了一套流式API,他不仅自带了JSON的解析器和生成器,还支持扩展数据格式,比如XMLCSVProtobuf
  • jackson-annotations 提供了处理数据时需要的注解
  • jackson-databind 可以将数据和Java对象进行绑定,使用起来更方便、更符合直觉

通常来说,我们提到Jackson的时候,指的就是jackson-databind,他直接依赖了jackson-core和jackson-annotations。我们用Jackson的时候,通常也只是用来处理JSON,其他数据格式可以参考官网进行扩展。

如何引入?

如果你使用Spring Boot开发web应用的话,Jackson已经内置在你的项目里了:

Jackson是Spring Boot的默认使用的

如果你在其他情况下使用,可以添加以下依赖(假设使用Gradle构建项目):

查询最新版本可以参照这里

快速开始

学习一个库的最快的方式就是通过实践来感受其作用。下图中的程序用简单的代码说明了如何根据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方法来往其中添加数据:

希望库里今年拿到FMVP

添加数组的时候,跟添加字符串或者整数的不太一样,putArray调用完毕后,会返回一个ArrayNode对象,在这个对象中添加数组内容会反应到最终的JSON串中。

Jackson的API非常丰富,上面做说的这些东西只能算是满足了常见的需求,我之后再写点文章详细说说

发表评论

电子邮件地址不会被公开。