2009-08-24 31 views
10

Trong mã Jackson/Java sau đó serializes đối tượng vào JSON, tôi nhận được điều này:Sử dụng Jackson ObjectMapper serialize tên lớp con vào JSON, không phải là lớp cha

{"animal":{"x":"x"}} 

Tuy nhiên, những gì tôi thực sự muốn có được là thế này:

{"dog":{"x":"x"}} 

có cái gì tôi có thể làm để AnimalContainer vì vậy mà tôi nhận được các loại thời gian chạy ("con chó", "con mèo") của đối tượng, thay vì "động vật")? (Chỉnh sửa: Tôi biết rằng tên bản đồ đến từ các tên phương thức getter và setter.) Cách duy nhất tôi có thể nghĩ là thực hiện nó nằm trong AnimalContainer để có thuộc tính của từng loại động vật, có setters và getters cho tất cả chúng, và thực thi rằng chỉ có một được định giá tại một thời điểm. Nhưng điều này đánh bại mục đích của việc có siêu lớp Thú vật và dường như sai. Và trong mã thực sự của tôi, tôi thực sự có một tá lớp con, không chỉ là "chó" và "mèo". Có cách nào tốt hơn để làm điều này (có lẽ bằng cách sử dụng chú thích bằng cách nào đó)? Tôi cần một giải pháp cho deserializing, là tốt.

public class Test 
{ 
    public static void main(String[] args) throws Exception 
    { 
     AnimalContainer animalContainer = new AnimalContainer(); 
     animalContainer.setAnimal(new Dog()); 

     StringWriter sw = new StringWriter(); // serialize 
     ObjectMapper mapper = new ObjectMapper(); 
     MappingJsonFactory jsonFactory = new MappingJsonFactory(); 
     JsonGenerator jsonGenerator = jsonFactory.createJsonGenerator(sw); 
     mapper.writeValue(jsonGenerator, animalContainer); 
     sw.close(); 
     System.out.println(sw.getBuffer().toString()); 
    } 
    public static class AnimalContainer 
    { 
     private Animal animal; 
     public Animal getAnimal() {return animal;} 
     public void setAnimal(Animal animal) {this.animal = animal;} 
    } 
    public abstract static class Animal 
    { 
     String x = "x"; 
     public String getX() {return x;} 
    } 
    public static class Dog extends Animal {} 
    public static class Cat extends Animal {} 
} 

Trả lời

9

Theo this announement, Jackson 1.5 triển khai xử lý loại đa hình đầy đủ và giờ đây thân cây đã tích hợp mã đó.

Có hai cách đơn giản để làm cho công việc này:

  • Thêm @JsonTypeInfo chú thích trong supertype (Animal đây), HOẶC
  • Cấu hình đối tượng mapper bằng cách gọi ObjectMapper.enableDefaultTyping() (nhưng nếu vậy, Animal cần phải là kiểu trừu tượng)
+1

có cách nào để giải quyết với 'ObjectMapper.enableDefaultTyping()' mà không cần Animal là Tóm tắt? Tôi đang sử dụng Jackson 1.9 và tôi đã thử nhưng vẫn không hoạt động ..... –

+0

Nhập mặc định có thể sử dụng các loại tiêu chí khác nhau, xem javadocs, bao gồm định nghĩa tùy chỉnh về những gì nó nên áp dụng. – StaxMan

0

Đây là cách duy nhất tôi có thể nghĩ đến để làm điều đó và điều đó thật xấu. Có cách nào tốt hơn?

@JsonWriteNullProperties(false) 
    public static class AnimalContainer 
    { 
     private Animal animal; 

     public Animal getCat() 
     { 
     return animal instanceof Cat ? animal : null; 
     } 
     public void setCat(Cat cat) 
     { 
     this.animal = cat; 
     } 
     public Animal getDog() 
     { 
     return animal instanceof Dog ? animal : null; 
     } 
     public void setDog(Dog dog) 
     { 
     this.animal = dog; 
     } 
     public Animal getFish() 
     { 
     return animal instanceof Fish ? animal : null; 
     } 
     public void setFish(Fish fish) 
     { 
     this.animal = fish; 
     } 
    } 
2

Đây có lẽ không phải là câu trả lời bạn đang tìm kiếm, nhưng có những kế hoạch để thực hiện đúng đắn "deserialization đa hình" (và hỗ trợ cần thiết về serialization cho nó), cho Jackson phiên bản 1.4 hoặc lâu hơn (tức là không tiếp theo một, 1,3, nhưng một sau đó). Đối với phiên bản hiện tại, bạn phải triển khai serializers/deserializers tùy chỉnh: tôi có thể chỉ định nghĩa phương thức factory cho deserialization, và getter type cho serializer (định nghĩa 'getAnimalType' hoặc bất cứ thứ gì trong abstract class abstract như abstract, override trong sub- các lớp - hoặc thậm chí chỉ thực hiện trong lớp cơ sở, tên lớp đầu ra của lớp thể hiện?).

Dù sao, chỉ trong trường hợp vấn đề, đây là tiềm ẩn những vấn đề wrt thực hiện xử lý các tiểu lớp học với JSON, và không có ngôn ngữ lược đồ (kể từ json không thực sự đã sử dụng rộng rãi một):

  • cách để tách dữ liệu (giá trị thuộc tính bean) khỏi siêu dữ liệu (chỉ cần nhập thông tin loại để tạo các lớp con thích hợp) - nhưng phải được giữ riêng biệt, nhưng JSON là định dạng không có cách nào để xác định (có thể sử dụng quy ước đặt tên)
  • cách thêm chú thích thích hợp để tạo và sử dụng siêu dữ liệu như vậy; và không phụ thuộc vào các tính năng cụ thể của ngôn ngữ (không cần phải gắn với tên lớp java chẳng hạn)

Đây là những vấn đề có thể giải quyết được, nhưng không dễ giải quyết. :-)

+0

Ít nhất điều này xác nhận rằng không có cách nào để thực hiện điều này trong Jackson (chưa), rằng tôi không thiếu gì; nó phải được thực hiện một cách khó khăn. – seansand

+0

Đúng - Tôi không thể nghĩ ra một cách để làm điều đó một cách dễ dàng (không có bộ chỉnh sửa tùy biến/deserializer) với Jackson 1.2 hoặc trước đó. – StaxMan

+0

FWIW, Jackson phiên bản 1.5 sẽ có hỗ trợ xử lý toàn diện đa hình cho quá trình deserialization (1.4 vừa được phát hành). – StaxMan

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