Backend Development 7 min read

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.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Master Custom JSON Serialization in Spring Boot 3 with @JsonComponent

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.

JavaJSONSpring BootJacksoncustom serialization
Spring Full-Stack Practical Cases
Written by

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.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.