Appearance
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