2015-02-07 12 views
7

Giả serialization để json bao gồm tên lớp của đối tượng thực tế, sử dụng chú thích này trên Class:Jackson có thể xác định loại đối tượng gốc để deserialize khi json bao gồm thuộc tính type?

@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@type") 
class MyClass { 
    String foo; 
} 

Vì vậy json là ví dụ:

{"@type": "com.example.MyClass", "foo": "bar"} 

này có thể được deserialized mà không chỉ định loại ? Và tôi có nghĩa là thậm chí không phải loại siêu. Chỉ cần một cái gì đó như:

objectMapper.readValue(value, Object.class); 

mà không thực sự làm việc, nó mang lại một bản đồ.

Trả lời

5

Vâng, chắc chắn có thể làm điều đó mặc dù cá nhân tôi chưa bao giờ sử dụng Jackson theo cách đó. Bạn có thể deserialize nó vào một đối tượng JsonNode và sau đó chuyển nó sang loại thích hợp.

final ObjectMapper objectMapper = new ObjectMapper(); 
final MyClass myClass = new MyClass(); 
myClass.foo = "bar"; 

// Serialize 
final String json = objectMapper.writeValueAsString(myClass); 

// Deserialize 
final JsonNode jsonNode = objectMapper.readTree(json); 

// Get the @type 
final String type = jsonNode.get("@type").asText(); 

// Create a Class-object 
final Class<?> cls = Class.forName(type); 

// And convert it 
final Object o = objectMapper.convertValue(jsonNode, cls); 

System.out.println(o.getClass()); 

Đầu ra là:

MyClass

+2

Ồ, vâng, tôi đoán nó hoạt động. Tôi đã tự hỏi nếu có một cách tích hợp hơn nhưng tôi đoán rằng sẽ không làm cho bất kỳ ý nghĩa như Jackson không thể biết làm thế nào tôi đã cấu hình JsonTypeInfo, mà không biết lớp. Cảm ơn rất nhiều. –

1

Vâng, nhưng có một caveat: gõ bạn cung cấp cho PHẢI là cái gì đó bao gồm @JsonTypeInfo bạn chỉ định. Object.class sẽ không có, trừ khi bạn sử dụng "chú thích kết hợp" để liên kết nó.

Tuy nhiên, nếu bạn cần thêm thông tin loại cho thuộc tính (loại đã khai báo) java.lang.Object, có thể bạn muốn bật nhập mặc định: xem ObjectMapper.enableDefaultTyping(...) để biết thêm thông tin. Điều đó thực sự sẽ cho phép bao gồm (và sử dụng) thông tin loại cho các loại lớp học lớn hơn, mà không cần phải thêm chú thích.

2
ObjectMapper mapper = new ObjectMapper(); 
    mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); 

    MyClass original = new MyClass(); 
    original.foo = "hello"; 

    String json = mapper.writeValueAsString(original); 
    MyClass foo = (MyClass) mapper.readValue(json, MyClass.class); 

Điều này sẽ hoạt động và rất thuận tiện.

+0

Nó hoạt động nếu bạn biết JSON đại diện cho 'MyClass' tại thời gian deserialization. Tôi lấy câu hỏi để chỉ một kịch bản mà bạn không biết loại đối tượng. Đó là tình huống tôi đang cố xử lý. –

+0

Nếu bạn không biết loại, bạn chỉ có thể gán cho một đối tượng. Object.getClass() sẽ cho bạn biết đó là kiểu gì. – sydraz

Các vấn đề liên quan