Codify Jackson usage rules. LLM default configuration SerializationFeature.WRITE_DATES_AS_TIMESTAMPS=true, but Chinese developers expect yyyy-MM-dd HH:mm:ss.
Capability Boundaries
✅ Strong Suits
- Date Format — yyyy-MM-dd HH:mm:ss (non-ISO-8601), integrated with Spring Boot
- Null Serialization — array→[]/string→""/number→null/boolean→null (rules must be explicit if inconsistent)
- @JsonView — the same object returns different fields in different scenarios (list vs detail)
- TypeReference — correctly deserialize generic types (List, etc.)
- @JsonProperty/@JsonFormat/@JsonIgnore — field renaming/formatting/ignoring
❌ Out of Scope
- Java Bean mapping → MapStruct(generated at compile time, Jackson is serialization not mapping)
- JSON is the API format, use MapStruct for internal object mapping
Errors LLMs most commonly make
| # | Mistake | Correct Approach |
|---|---|---|
| 1 | Date serialized as timestamp 1702468800000 |
Configure WRITE_DATES_AS_TIMESTAMPS=false, format yyyy-MM-dd HH:mm:ss |
| 2 | null fields not returned or returned as null | Explicit rules: array→[], string→"", number→null, boolean→null |
| 3 | new ObjectMapper() every time | ObjectMapper is thread-safe, use an application-level singleton |
| 4 | objectMapper.readValue(json, List.class) |
objectMapper.readValue(json, new TypeReference<List<User>>(){}) |
| 5 | Standard JSON format not aligned with other systems | NullNode/WRITE_BIGDECIMAL_AS_PLAIN, etc. require explicit configuration |
Core Rules Quick Reference
// ✅ Spring Boot 配置(ObjectMapper全局)
@Configuration
public class JacksonConfig {
@Bean
public Jackson2ObjectMapperBuilderCustomizer customizer() {
return builder -> builder
.simpleDateFormat("yyyy-MM-dd HH:mm:ss")
.serializationInclusion(JsonInclude.Include.NON_NULL)
.featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
.featuresToEnable(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES);
}
}
// ✅ 注解方式
@Data
public class UserVO {
@JsonProperty("user_name") // JSON字段重命名
private String username;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createTime;
@JsonIgnore // 序列化时忽略
private String password;
@JsonView(Views.Detail.class) // 仅详情视图返回
private String email;
}
// ✅ TypeReference 反序列化
List<User> users = objectMapper.readValue(json,
new TypeReference<List<User>>(){});
// ✅ Null值处理规则
objectMapper.configOverride(String.class)
.setInclude(JsonInclude.Value.construct(
JsonInclude.Include.NON_NULL, // null string → null
JsonInclude.Include.NON_NULL
));
Gotchas
- ObjectMapper is thread-safe — don't new it every time, use a singleton
- TypeReference is essential — generic deserialization without TypeReference yields a LinkedHashMap
- @JsonProperty only affects serialization — does not affect the Java field name
- WRITE_DATES_AS_TIMESTAMPS defaults to true — Spring Boot changes the default to false
- Jackson's @JsonFormat and Spring's @DateTimeFormat are different — the former for JSON, the latter for form/Query parameters
- Cannot deserialize LocalDateTime by default — requires the jackson-datatype-jsr310 dependency
- Difference between @JsonIgnore and @JsonProperty(access=READ_ONLY) — @JsonIgnore ignores both directions, access controls the direction
- A null number does not automatically become 0 — requires a global include=NON_NULL or individual configuration
Data Privacy
This skill does not collect, store, or transmit any user data.