Những thuộc tính nào được Jackson chọn để Serialization/Deserialization

Chúng ta có bao giờ đặt ra câu hỏi làm thế nào để Jackson có thể chọn những thuộc tính (field) được serialized /deserialized không? Đôi lúc chỉ cần cho nó field public, getter, setter. Thật là mơ hồ phải không, trong bài viết này chúng ta sẽ cùng nhau làm rõ vấn đề này.

Public Field

Cách đơn giản nhất để đảm bảo một field trong Java class được serialized /deserialized là đặt cho nó public acccess modifier.

Ví dụ tạo một MyDtoAccessLevel chứa đầy đủ các access modifier, lưu ý không thêm getter, setter method.

public class MyDtoAccessLevel {
    private String stringValue;
    int intValue;
    protected float floatValue;
    public boolean booleanValue;
    // NO setters or getters
}

Trong 4 field trên, booleanValue sẽ được serialized sang Json.

ObjectMapper mapper = new ObjectMapper();

MyDtoAccessLevel dtoObject = new MyDtoAccessLevel();
String dtoAsString = mapper.writeValueAsString(dtoObject);
System.out.println(dtoAsString); // {"booleanValue":false}

Non-Public field với Getter method

Một cách khác, chúng ta có thể khiến một field – đặc biệt là non-public field sẽ tham gia vào serialization.

public class MyDtoWithGetter {
    private String stringValue;
    private int intValue;
 
    public String getStringValue() {
        return stringValue;
    }
}

Đối với MyDtoWithGetter, chúng ta mong muốn rằng stringValue sẽ được serialized, trong khi private field intValue thì không.

ObjectMapper mapper = new ObjectMapper();

MyDtoWithGetter dtoObject = new MyDtoWithGetter();

String dtoAsString = mapper.writeValueAsString(dtoObject);
System.out.println(dtoAsString); // {"stringValue":null}

Vô tình, getter method cũng có thể làm cho một private field được deserializable.

String jsonAsString = "{\"stringValue\":\"dtoString\"}";
ObjectMapper mapper = new ObjectMapper();
MyDtoWithGetter dtoObject = mapper.readValue(jsonAsString, MyDtoWithGetter.class);
System.out.println(dtoObject.getStringValue()); // dtoString

Setter method với Non – Public filed

Chúng ta đã thấy được rằng getter method đã làm cho một non – private filed được serialized /deserialized. Tuy nhiên setter method chỉ cho phép các field được deserializable.

public class MyDtoWithSetter {
    private int intValue;
 
    public void setIntValue(int intValue) {
        this.intValue = intValue;
    }
 
    public int accessIntValue() {
        return intValue;
    }
}

Các bạn có thể thấy intValue chỉ chứa setter method, accessIntValue() được xem như là một cách để truy cập giá trị của intValue, nhưng nó không được tính là getter method.

String jsonAsString = "{\"intValue\":1}";
ObjectMapper mapper = new ObjectMapper();

MyDtoWithSetter dtoObject = mapper.readValue(jsonAsString, MyDtoWithSetter.class);
System.out.println(dtoObject.accessIntValue()); // 1

Như đã nói ở trên, setter sẽ không thể khiến cho các field được serializable.

Nếu thực thi đoạn code dưới đây sẽ dẫn đến InvalidDefinitionException

ObjectMapper mapper = new ObjectMapper();

MyDtoWithSetter dtoObject = new MyDtoWithSetter(1);

String dtoAsString = mapper.writeValueAsString(dtoObject);

Cho phép tất cả các field được serialized

Trong một số trường hợp, chúng ta không muốn sửa trực tiếp mã nguồn của Java class, nhưng vẫn muốn tất cả các field kể cả non-public đều được serialized. Điều này hoàn toàn có thể thực hiện được bằng cách bật chế độ AutoDetect ObjectMapper để sử dụng public field hoặc getter/setter method cho serialization, hoặc có thể serialization cho tất cả các field.

ObjectMapper mapper = new ObjectMapper();
mapper.setVisibility(PropertyAccessor.ALL, Visibility.NONE);
mapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);

Ví dụ cho phép tất cả các field trong MyDtoAccessLevel class đều được serialized.

ObjectMapper mapper = new ObjectMapper();
mapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);

MyDtoAccessLevel dtoObject = new MyDtoAccessLevel();
String dtoAsString = mapper.writeValueAsString(dtoObject);
System.out.println(dtoAsString);
// {"stringValue":null,"intValue":0,"floatValue":0.0,"booleanValue":false}

Tóm lược

Như vậy là chúng ta đã biết cách Jackson xác định các field nào của Java class có thể serialized/deserialized. Những public field sẽ luôn được Jackson chọn, trong khi getter method cho phép ở serialized/deserialized thì setter chỉ cho phép deserialized.

Nguồn tham khảo

https://www.baeldung.com/jackson-field-serializable-deserializable-or-not

0 0 votes
Article Rating
Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x