Master Custom JSON Serialization in Spring Boot 3 with @JsonComponent
This tutorial demonstrates how to programmatically customize JSON serialization and deserialization in Spring Boot by implementing JsonSerializer, JsonDeserializer, JsonObjectSerializer, and JsonObjectDeserializer, complete with code examples, test endpoints, and important usage notes.
1. Introduction
The article explains how to customize JSON serialization and deserialization in Spring Boot using a programming approach, complementing the annotation‑based method previously covered.
2. Practical Example
By annotating a class with @JsonComponent , you can directly register custom JsonSerializer and JsonDeserializer implementations.
<code>@JsonComponent
public class PackJsonComponent {
// Custom serializer
public static class Serializer extends JsonSerializer<User> {
@Override
public void serialize(User value, JsonGenerator jgen, SerializerProvider serializers) throws IOException {
jgen.writeStartObject();
jgen.writeStringField("name", value.getName());
jgen.writeNumberField("age", value.getAge());
jgen.writeEndObject();
}
}
// Custom deserializer
public static class Deserializer extends JsonDeserializer<User> {
@Override
public User deserialize(JsonParser jsonParser, DeserializationContext ctxt) throws IOException {
ObjectCodec codec = jsonParser.getCodec();
JsonNode tree = codec.readTree(jsonParser);
String name = tree.get("name").textValue();
int age = tree.get("age").intValue();
long id = tree.get("id").longValue() + 1000L; // added for demonstration
return new User(id, name, age);
}
}
}
</code>The following controller demonstrates the usage of the custom components:
<code>@RestController
@RequestMapping("/jackson")
public class JacksonController {
@GetMapping("/user")
public User queryUser() {
return new User(1L, "Zhang San", 10);
}
@PostMapping("/save")
public User saveUser(@RequestBody User user) {
return user;
}
}
// User class
public class User {
private Long id;
private String name;
private Integer age;
// getters and setters
}
</code>Testing the /user and /save endpoints returns the expected JSON, as shown in the screenshots below.
All beans annotated with @JsonComponent are automatically registered with Jackson because the annotation itself is meta‑annotated with @Component , so standard component‑scanning rules apply.
Spring Boot also provides JsonObjectSerializer and JsonObjectDeserializer base classes for more flexible handling:
<code>@JsonComponent
public class PackJsonComponent {
public static class Serializer extends JsonObjectSerializer<User> {
@Override
protected void serializeObject(User value, JsonGenerator jgen, SerializerProvider provider) throws IOException {
jgen.writeNumberField("id", value.getId());
jgen.writeStringField("name", value.getName());
jgen.writeNumberField("age", value.getAge());
jgen.writeStringField("nation", "China🇨🇳");
Map<String, Object> params = new HashMap<>();
params.put("q", "java");
params.put("s", "pack");
jgen.writeObjectField("params", params);
}
}
public static class Deserializer extends JsonObjectDeserializer<User> {
@Override
protected User deserializeObject(JsonParser jsonParser, DeserializationContext context, ObjectCodec codec, JsonNode tree) throws IOException {
long id = nullSafeValue(tree.get("id"), Long.class) + 1L;
String name = nullSafeValue(tree.get("name"), String.class);
int age = nullSafeValue(tree.get("age"), Integer.class);
return new User(id, name, age);
}
}
}
</code>Note that you must not call jgen.writeObject(value) inside a custom serializer, as it will cause an error; instead, write individual fields or other objects as demonstrated.
<code>// Incorrect usage – will throw an exception
jgen.writeObject(value);
</code>All custom serializers/deserializers only affect the specific generic type they target; other types remain unaffected.
Spring Full-Stack Practical Cases
Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.
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.