Annotation @JsonSerialize khai báo custom serializer khi chuyển Java object → JSON. Implement bằng cách extends StdSerializer<T> và override serialize().
Cú pháp
@Target({ANNOTATION_TYPE, METHOD, FIELD, TYPE, PARAMETER})
@Retention(RUNTIME)
public @interface JsonSerialize {
Class<? extends JsonSerializer<?>> using() default JsonSerializer.None.class;
}
Ví dụ hoàn chỉnh
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.annotation.*;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
public class JsonSerializeTest {
public static void main(String[] args) throws Exception {
ObjectMapper mapper = new ObjectMapper();
Employee emp = new Employee(115, "Adithya", new String[]{"Java", "Python", "Scala"});
String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(emp);
System.out.println(json);
}
}
// Custom Serializer
class CustomSerializer extends StdSerializer<Employee> {
public CustomSerializer() { this(Employee.class); }
public CustomSerializer(Class<Employee> t) { super(t); }
@Override
public void serialize(Employee emp, JsonGenerator jgen, SerializerProvider provider)
throws IOException {
jgen.writeStartObject();
jgen.writeNumberField("id", emp.getId());
jgen.writeStringField("name", emp.getName());
// Gộp mảng languages thành một string phân cách bằng ;
StringBuilder sb = new StringBuilder();
for (String s : emp.getLanguages()) {
sb.append(s).append(";");
}
jgen.writeStringField("languages", sb.toString());
jgen.writeEndObject();
}
}
// Entity với @JsonSerialize
@JsonSerialize(using = CustomSerializer.class)
class Employee {
private int id;
private String name;
private String[] languages;
public Employee(int id, String name, String[] languages) {
this.id = id;
this.name = name;
this.languages = languages;
}
public int getId() { return id; }
public String getName() { return name; }
public String[] getLanguages() { return languages; }
}
Output
{
"id" : 115,
"name" : "Adithya",
"languages" : "Java;Python;Scala;"
}
Các trường hợp dùng custom serializer
- Format output đặc biệt: date format custom, mask sensitive data (credit card, password).
- Flatten/transform structure: gộp array thành string, đổi tên field.
- Conditional serialization: chỉ serialize field nếu thỏa điều kiện.
- Polymorphic serialization: thêm type discriminator.
Best Practice
- Dùng
JsonGeneratorAPI (streaming) để hiệu suất tốt, tránh build object trung gian. - Đăng ký qua
SimpleModulecho global config:module.addSerializer(Employee.class, new CustomSerializer()). - Kết hợp
@JsonFormatcho date/number đơn giản thay vì custom serializer phức tạp. - Jackson 2.12+: Hỗ trợ
@JsonSerialize(converter = ...)cho converter đơn giản hơn serializer đầy đủ.