Customizing JSON Serialization and Deserialization in Spring Boot
In Spring Boot you can customize JSON request and response handling by annotating fields with @JsonSerialize/@JsonDeserialize, registering a global ObjectMapper module, adding a PropertyEditor via @ControllerAdvice, creating a custom HttpMessageConverter, or using AOP interception, selecting the approach that matches your project’s complexity.
In Spring Boot, customizing request and response JSON can be achieved by several approaches.
1. Use @JsonSerialize and @JsonDeserialize on fields to specify custom serializer/deserializer.
public class CustomLocalDateTimeSerializer extends JsonSerializer<LocalDateTime> {
@Override
public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
gen.writeString(value.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
}
}
public class CustomLocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> {
@Override
public LocalDateTime deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
return LocalDateTime.parse(p.getValueAsString(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
}
}
public class MyEntity {
@JsonSerialize(using = CustomLocalDateTimeSerializer.class)
@JsonDeserialize(using = CustomLocalDateTimeDeserializer.class)
private LocalDateTime dateTime;
// getters and setters
}2. Configure a global ObjectMapper by registering a custom module.
public class CustomJacksonModule extends SimpleModule {
public CustomJacksonModule() {
addSerializer(LocalDateTime.class, new CustomLocalDateTimeSerializer());
addDeserializer(LocalDateTime.class, new CustomLocalDateTimeDeserializer());
}
}
@Bean
public Jackson2ObjectMapperBuilderCustomizer jsonCustomizer() {
return builder -> builder.modules(new CustomJacksonModule());
}3. Use @ControllerAdvice with @InitBinder to register a custom PropertyEditor for form data.
public class CustomLocalDateTimeEditor extends PropertyEditorSupport {
@Override
public void setAsText(String text) {
setValue(LocalDateTime.parse(text, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
}
@Override
public String getAsText() {
LocalDateTime value = (LocalDateTime) getValue();
return value.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
}
}
@ControllerAdvice
public class CustomControllerAdvice {
@InitBinder
public void initBinder(WebDataBinder binder) {
binder.registerCustomEditor(LocalDateTime.class, new CustomLocalDateTimeEditor());
}
}4. Implement a custom HttpMessageConverter to handle specific media types.
public class CustomLocalDateTimeConverter extends MappingJackson2HttpMessageConverter {
public CustomLocalDateTimeConverter() {
ObjectMapper customObjectMapper = new ObjectMapper();
customObjectMapper.registerModule(new CustomJacksonModule());
setObjectMapper(customObjectMapper);
}
}
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(0, new CustomLocalDateTimeConverter());
}
}5. Apply Spring AOP to intercept controller methods and modify input/output, though using AOP for JSON transformation is generally discouraged.
@Aspect
@Component
public class CustomSerializationAspect {
@Before("execution(* com.example.controller..*.*(..)) && args(..,@RequestParam(..),@RequestBody(..))")
public void beforeControllerMethod(JoinPoint joinPoint) { /* optional */ }
@AfterReturning(pointcut = "execution(* com.example.controller..*.*(..)) && @annotation(org.springframework.web.bind.annotation.RequestMapping)", returning = "result")
public void afterControllerMethod(JoinPoint joinPoint, Object result) { /* optional */ }
}Choose the method that fits the project’s complexity: simple field‑level changes with annotations, global mapper configuration, or a full‑blown converter/AOP for advanced scenarios.
Java Tech Enthusiast
Sharing computer programming language knowledge, focusing on Java fundamentals, data structures, related tools, Spring Cloud, IntelliJ IDEA... Book giveaways, red‑packet rewards and other perks await!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.