Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Java

วิธีสร้าง Custom Serializer ด้วย Jackson ใน Java

Jackson API ให้ความยืดหยุ่นในการ serialize object โดยการ implement Custom Serializer ผ่านการ extends คลาส StdSerializer<T> และ override เมธอด serialize(T value, JsonGenerator gen, SerializerProvider provider)

Signature ของเมธอด serialize


public abstract void serialize(T value, JsonGenerator gen, SerializerProvider provider) 
    throws IOException, JsonProcessingException

พารามิเตอร์:

  • value - object ที่จะ serialize (ไม่เป็น null)
  • gen - JsonGenerator สำหรับเขียน JSON output
  • provider - SerializerProvider สำหรับดึง serializer อื่นๆ มาใช้

ตัวอย่างโค้ดครบถ้วน


import java.io.*;
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;

public class JacksonCustomSerializerTest {
    public static void main(String[] args) throws Exception {
        User user = new User();
        user.setFirstName("Raja");
        user.setLastName("Ramesh");
        
        ObjectMapper mapper = new ObjectMapper();
        SimpleModule module = new SimpleModule();
        module.addSerializer(User.class, new UserSerializer());
        mapper.registerModule(module);
        
        String jsonStr = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(user);
        System.out.println(jsonStr);
    }
}

// User class (POJO)
class User implements Serializable {
    private String firstName;
    private String lastName;
    
    public String getFirstName() { return firstName; }
    public void setFirstName(String firstName) { this.firstName = firstName; }
    public String getLastName() { return lastName; }
    public void setLastName(String lastName) { this.lastName = lastName; }
}

// Custom Serializer
class UserSerializer extends StdSerializer<User> {
    public UserSerializer() { this(null); }
    public UserSerializer(Class<User> t) { super(t); }
    
    @Override
    public void serialize(User value, JsonGenerator jgen, SerializerProvider provider) 
            throws IOException {
        jgen.writeStartObject();
        jgen.writeStringField("firstName", value.getFirstName());
        jgen.writeStringField("lastName", value.getLastName());
        // สามารถเพิ่ม computed field ได้
        jgen.writeStringField("fullName", value.getFirstName() + " " + value.getLastName());
        jgen.writeEndObject();
    }
}

ผลลัพธ์


{
  "firstName" : "Raja",
  "lastName" : "Ramesh",
  "fullName" : "Raja Ramesh"
}

การใช้งานขั้นสูง

1. ใช้ JsonSerializer แทน StdSerializer (Generic)


class UserSerializer extends JsonSerializer<User> {
    @Override
    public void serialize(User value, JsonGenerator gen, SerializerProvider provider) 
            throws IOException { ... }
}

2. ใช้ ContextualSerializer สำหรับการ configure แบบ dynamic


class UserSerializer extends StdSerializer<User> implements ContextualSerializer {
    private boolean includeFullName;
    
    public UserSerializer() { this(null); }
    public UserSerializer(Class<User> t) { super(t); }
    
    @Override
    public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty prop) {
        JsonInclude inc = prop.getAnnotation(JsonInclude.class);
        boolean include = inc != null; // logic ตัดสินใจ
        return new UserSerializer(include);
    }
    // ...
}

3. ใช้ @JsonSerialize บน field/class โดยตรง


class Employee {
    @JsonSerialize(using = UserSerializer.class)
    private User user;
    // ...
}

เมื่อไหร่ควรใช้ Custom Serializer

  • ต้องการเปลี่ยนชื่อฟิลด์ / โครงสร้าง JSON ให้ต่างจาก POJO
  • ต้องคำนวณค่าเพิ่มเติม (computed fields)
  • ต้อง serialize object ที่ไม่ได้ควบคุม source code (third-party class)
  • ต้องจัดการ circular reference เอง
  • ต้องการ format เฉพาะ (เช่น date format custom)

ข้อควรระวัง

  • ต้องจดทะเบียนผ่าน SimpleModule และ mapper.registerModule()
  • Custom serializer จะ override annotation ทั้งหมดบน class นั้น
  • ประสิทธิภาพ: JsonGenerator เขียน streaming ตรงๆ เร็วกว่าสร้าง tree model