JSON

olinonee大约 4 分钟spring-all编程SpringBoot 框架

JSON

Spring Boot 提供了与三个 JSON 映射库的集成:

  • Gson
  • Jackson
  • JSON-B

Jackson 是首选和默认库。

1.Jackson

提供了 Jackson 的自动配置,Jackson 是 spring-boot-start-json 的一部分。当 Jackson 位于类路径上时,将自动配置一个 ObjectMapper bean。为定制 ObjectMapper 的配置提供了几个配置属性。

自定义序列化器和反序列化器

如果使用 Jackson 序列化和反序列化 JSON 数据,可能需要编写自己的 JsonSerializerJsonDeserializer 类。自定义序列化器通常通过模块注册到 Jacksonopen in new window,但 Spring Boot 提供了另一种 @JsonComponent 注解,可以更容易地直接注册 Spring bean。

可以直接在 JsonSerializerJsonDeserializerKeyDeserializer 实现上使用 @JsonComponent 注解。你还可以在包含序列化程序/反序列化程序作为内部类的类上使用它,如下例所示:

MyJsonComponent.java

import com.fasterxml.jackson.core.JacksonException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.ObjectCodec;
import com.fasterxml.jackson.databind.*;
import org.springframework.boot.jackson.JsonComponent;

import java.io.IOException;

@JsonComponent
public class MyJsonComponent {

    /**
     * 序列化
     */
    public static class Serializer extends JsonSerializer<MyObject> {

        @Override
        public void serialize(MyObject myObject, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
            jsonGenerator.writeStartObject();
            jsonGenerator.writeStringField("name", myObject.getName());
            jsonGenerator.writeNumberField("age", myObject.getAge());
            jsonGenerator.writeEndObject();
        }
    }

    /**
     * 反序列化
     */
    public static class Deserializer extends JsonDeserializer<MyObject> {

        @Override
        public MyObject deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException {
            final ObjectCodec codec = jsonParser.getCodec();
            final JsonNode treeNode = codec.readTree(jsonParser);
            final String name = treeNode.get("name").textValue();
            final int age = treeNode.get("age").intValue();
            return new MyObject(name, age);
        }
    }
}

MyObject.java

public class MyObject {
    private String name;
    private int age;

    public MyObject(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // getter, setter
}

ApplicationContext 中的所有 @JsonComponent bean 都会自动向 Jackson 注册。因为 @JsonComponent 是用 @Component 元注解的,所以通常的组件扫描规则适用。

Spring Boot 还提供了 JsonObjectSerializeropen in new windowJsonObjectDeserializeropen in new window 基类,这些基类在序列化对象时为标准 Jackson 版本提供了有用的替代方案。有关详细信息,请参阅 Javadoc 中的 JsonObjectSerializeropen in new windowJsonObjectDeserializeropen in new window

上面的例子可以使用 JsonObjectSerializer/JsonObjectDeserializer 重写,如下所示:

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.ObjectCodec;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.SerializerProvider;
import org.springframework.boot.jackson.JsonComponent;
import org.springframework.boot.jackson.JsonObjectDeserializer;
import org.springframework.boot.jackson.JsonObjectSerializer;

import java.io.IOException;

@JsonComponent
public class MyJSONObjectComponent {

    /**
     * 序列化
     */
    public static class Serializer extends JsonObjectSerializer<MyObject> {

        @Override
        protected void serializeObject(MyObject value, JsonGenerator jgen, SerializerProvider provider) throws IOException {
            jgen.writeStringField("name", value.getName());
            jgen.writeNumberField("age", value.getAge());
        }
    }

    /**
     * 反序列化
     */
    public static class Deserializer extends JsonObjectDeserializer<MyObject> {

        @Override
        protected MyObject deserializeObject(JsonParser jsonParser, DeserializationContext context, ObjectCodec codec, JsonNode tree) throws IOException {
            final String name = nullSafeValue(tree.get("name"), String.class);
            final int age = nullSafeValue(tree.get("age"), Integer.class);
            return new MyObject(name, age);
        }
    }
}

混合

Jackson 支持 mixin,它可以用来将额外的注解混合到目标类中已经声明的注解中。Spring Boot 的 Jackson 自动配置将扫描应用程序包中带有 @JsonMixin 注解的类,并将它们注册到自动配置的 ObjectMapper 中。注册是由 Spring Boot 的 JsonMixinModule 执行的。

常用配置和常用注解

常用配置
# 日期格式字符串或标准日期格式类全限定名,只控制 java.util.Date 的序列化 format
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
# 指定 Joda date/time 的格式,比如 yyyy-MM-ddHH:mm:ss. 如果没有配置的话,dateformat 会作为 backup。
spring.jackson.joda-date-time-format=yyyy-MM-dd HH:mm:ss
# 全局设置 pojo 或被 @JsonInclude 注解的属性的序列化方式
spring.jackson.default-property-inclusion=NON_NULL
# 不为空的属性才会序列化,具体属性可看 JsonInclude.Include
# 是否开启 Jackson 的序列化
# 示例:spring.jackson.serialization.indent-output= true
spring.jackson.serialization.*=
# 是否开启 Jackson 的反序列化
spring.jackson.deserialization.*=
# 是否开启 json 的 generators
# 示例:spring.jackson.generator.auto-close-json-content=true
spring.jackson.generator.*=
# 指定 json 使用的 Locale
spring.jackson.locale=zh
# 是否开启Jackson通用的特性
spring.jackson.mapper.*=
# 是否开启 jackson 的 parser 特性
spring.jackson.parser.*=
# 指定 Json 策略模式
spring.jackson.property-naming-strategy=com.fasterxml.jackson.databind.PropertyNamingStrategy.UpperCamelCaseStrategy
# 或
# spring.jackson.property-naming-strategy=UPPER_CAMEL_CASE
# 指定日期格式化时区,比如 Asia/Shanghai 或者 GMT+8
spring.jackson.time-zone=GMT+8
常用注解
  • @JsonPropertyOrder(value={“value1”,“value2”,“value3”}):将实体对应转换后默认 json 顺序,根据注解要求进行变换
  • @JsonIgnore:将某字段排除在序列化和反序列化之外
  • @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8"):按照指定日期格式进行转换
  • @JsonProperty("邮箱"):给对应字段起别名
  • @JsonInclude(JsonInclude.Include.NON_NULL):如果字段为空则不做序列化和反序列化
扩展

更多关于 Jackson 的使用,可以参考如下链接:

2.Gson

提供了 GSON 的自动配置。当 gson 在类路径上时,会自动配置一个 gson Bean。提供了几个 spring.gson.* 配置属性用于定制配置。要获得更多控制,可以使用一个或多个 GsonBuilderCustomizer Bean。

3.JSON-B

提供了 JSON-B 的自动配置。当 JSON-B API 和实现在类路径上时,将自动配置 Jsonb bean。首选的 JSON-B 实现是 Apache Johnzon,它提供了依赖管理。