Skip to content

Jackson 开发技巧

配置 ObjectMapper

java
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import org.springframework.context.annotation.Bean;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;

import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.TimeZone;

public class Config {

    private static final String DATE_FORMAT = "yyyy-MM-dd";
    private static final String TIME_FORMAT = "HH:mm:ss";
    private static final String DATETIME_FORMAT = "yyyy-MM-dd HH:mm:ss";

    @Bean
    public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) {
        ObjectMapper objectMapper = new ObjectMapper();

        // 注册Java 8时间模块(支持LocalDateTime等新日期类型的处理)
        objectMapper.registerModule(javaTimeModuleInstance());

        // 统一日期格式
        objectMapper.setDateFormat(new SimpleDateFormat(DATETIME_FORMAT));

        // 设置时区为东八区
        objectMapper.setTimeZone(TimeZone.getTimeZone("UTC+8"));

        // 禁用日期序列化为时间戳(默认Date会转为时间戳,如1672531200000)
        objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);

        // 配置序列化 启用JSON输出的缩进
        objectMapper.enable(SerializationFeature.INDENT_OUTPUT);

        // 设置序列化时忽略null值的字段
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);

        // 属性命名策略
        objectMapper.setPropertyNamingStrategy(PropertyNamingStrategies.LOWER_CAMEL_CASE);

        // 忽略JSON中的未知字段
        objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);

        return objectMapper;
    }

    private JavaTimeModule javaTimeModuleInstance() {
        JavaTimeModule javaTimeModule = new JavaTimeModule();

        // LocalDateTime序列化:格式化为"yyyy-MM-dd HH:mm:ss"
        javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(
                DateTimeFormatter.ofPattern(DATETIME_FORMAT)
        ));

        // LocalDate序列化:格式化为"yyyy-MM-dd"
        javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(
                DateTimeFormatter.ofPattern(DATE_FORMAT)
        ));

        // LocalTime序列化:格式化为"HH:mm:ss"
        javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(
                DateTimeFormatter.ofPattern(TIME_FORMAT)
        ));

        // LocalDateTime反序列化:从"yyyy-MM-dd HH:mm:ss"解析
        javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(
                DateTimeFormatter.ofPattern(DATETIME_FORMAT)
        ));

        // LocalDate反序列化:从"yyyy-MM-dd"解析
        javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(
                DateTimeFormatter.ofPattern(DATE_FORMAT)
        ));

        // LocalTime反序列化:从"HH:mm:ss"解析
        javaTimeModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer(
                DateTimeFormatter.ofPattern(TIME_FORMAT)
        ));

        return javaTimeModule;
    }

}

序列化

java
@Bean
public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) {
    ObjectMapper objectMapper = builder.build();
    SimpleModule simpleModule = new SimpleModule();
    simpleModule.addSerializer(CustomType.class, new CustomTypeSerializer());
    objectMapper.registerModule(simpleModule);
    return objectMapper;
}

// 注解声明,替换上述 ObjectMapper 
@JsonSerialize(using = CustomTypeSerializer.class) 
public class CustomType {
    private String value;

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }
}

public class CustomTypeSerializer extends StdSerializer<CustomType> {

    public CustomTypeSerializer() {
        this(null);
    }

    public CustomTypeSerializer(Class<CustomType> t) {
        super(t);
    }

    @Override
    public void serialize(CustomType value, JsonGenerator gen, SerializerProvider provider) throws IOException {
        gen.writeString(value.getValue().toUpperCase());
    }

}

反序列化

java
@Bean
public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) {
    ObjectMapper objectMapper = builder.build();
    SimpleModule simpleModule = new SimpleModule();
    simpleModule.addDeSerializer(CustomType.class, new CustomTypeDeSerializer());
    objectMapper.registerModule(simpleModule);
    return objectMapper;
}

// 注解声明,替换上述 ObjectMapper 
@JsonDeserialize(using = CustomTypeDeserializer.class)
public class CustomType {
    private String value;

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }
}

public class CustomTypeDeserializer extends StdDeserializer<CustomType> {

    public CustomTypeDeserializer() {
        this(null);
    }

    public CustomTypeDeserializer(Class<?> vc) {
        super(vc);
    }

    @Override
    public CustomType deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JacksonException {
        JsonNode node = jp.getCodec().readTree(jp);
        String value = node.get("value").asText();
        CustomType customType = new CustomType();
        customType.setValue(value);
        return customType;
    }

}

JSON View 视图

定义 JSON 视图

java
public class Views {
    public interface Public {}
    public interface Internal extends Public {}
}

注解字段

java
public class User {
    @JsonView(Views.Public.class)
    private String username;
    @JsonView(Views.Internal.class)
    private String email;
}

控制器中使用 JSON 视图

java
@JsonView(Views.Public.class) // { username }
@GetMapping("/public/users")
public List<User> getPublicUsers() {
}

@JsonView(Views.Internal.class) // { username, email }
@GetMapping("/internal/users")
public List<User> getInternalUsers() {
}

混合

java
public class User {
    @JsonProperty("name")
    private String name;
}

@JsonMixin(User.class)
public class BaseInfoMixin {
    @JsonProperty("fullName")
    private String name;
}

@GetMapping
public User get() {
    return new User(1L, "王五", 10);
}

/**
 * id: 1
 * age: 10
 * fullName: 王五
 */

多态 @JsonTypeInfo @JsonSubTypes

java
/**
 * 动物抽象基类
 * 使用Jackson注解实现多态类型的序列化/反序列化
 */
@JsonTypeInfo(
    use = JsonTypeInfo.Id.NAME,          // 使用子类名称作为类型标识
    include = JsonTypeInfo.As.PROPERTY,  // 类型信息作为独立字段嵌入JSON
    property = "type"                    // 类型字段名为"type"
)
@JsonSubTypes({
    @JsonSubTypes.Type(value = Dog.class, name = "dog"),  // 子类Dog对应标识"dog"
    @JsonSubTypes.Type(value = Cat.class, name = "cat")   // 子类Cat对应标识"cat"
})
public abstract class Animal {
    private String name;  // 公共属性:动物名称

    // Getter/Setter
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
java
/**
 * 狗子类
 * 继承Animal并添加特有属性breed(品种)
 */
public class Dog extends Animal {
    private String breed;  // 特有属性:品种

    // Getter/Setter
    public String getBreed() {
        return breed;
    }

    public void setBreed(String breed) {
        this.breed = breed;
    }
}
java
/**
 * 猫子类
 * 继承Animal并添加特有属性isStray(是否流浪猫)
 * 注意:布尔类型属性的Getter命名规范为isXXX()
 */
public class Cat extends Animal {
    private boolean isStray;  // 特有属性:是否流浪猫

    // Getter/Setter
    public boolean isStray() {
        return isStray;
    }

    public void setStray(boolean stray) {
        isStray = stray;
    }
}

示例代码

java
import com.fasterxml.jackson.databind.ObjectMapper;

public class Main {
    public static void main(String[] args) throws Exception {
        ObjectMapper mapper = new ObjectMapper();

        // 示例1:序列化Dog对象
        Dog dog = new Dog();
        dog.setName("Buddy");
        dog.setBreed("Golden Retriever");
        String dogJson = mapper.writeValueAsString(dog);
        System.out.println("Dog JSON: " + dogJson);
        // 输出: {"type":"dog","name":"Buddy","breed":"Golden Retriever"}

        // 示例2:反序列化Cat JSON
        String catJson = "{\"type\":\"cat\",\"name\":\"Whiskers\",\"isStray\":true}";
        Animal cat = mapper.readValue(catJson, Animal.class);
        System.out.println("Cat is stray? " + ((Cat) cat).isStray());
        // 输出: Cat is stray? true
    }
}

属性包含与排除 @JsonInclude @JsonIgnore

java
public class User {
    private String name;
    @JsonInclude(JsonInclude.Include.NON_NULL) // 当 mark 值不为空才会包含
    private String mark;
    @JsonIgnore // 忽略 password 属性
    private String password;
}

更新: 2025-07-19 16:54:01
原文: https://www.yuque.com/lsxxyg/sz/nob3nbheacs1cgdb