2012-01-20 8 views
7

Tôi đang cố gắng viết trình chỉnh sửa tùy chỉnh cho Jackson và tôi muốn làm cho nó chung chung (chung theo ý nghĩa làm việc trên bất kỳ loại nào, không giống như trong "generics").Custom Jackson Deserializer Nhận quyền truy cập vào Lớp hiện tại

Tuy nhiên, tôi không thể tìm ra cách xử lý loại trường đang được deserialized.

Ví dụ, tôi đang tìm cách để làm điều gì đó như sau:

@Override 
public MyObject deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { 

     Class c = <get type of current field> 
     // do something with that type 
     return new SubclassOfC(somedata based on c); 
} 

Đó là đặc biệt là loại get của lĩnh vực hiện tại phần mà tôi đã phải vật lộn với.

Edit: Đây là loại lĩnh vực java Tôi quan tâm đến

+0

Bằng cách "loại trường hiện nay", làm bạn có nghĩa là loại giá trị JSON (đối tượng, mảng, chuỗi, int, vv)? Hoặc loại của một trường Java có cùng tên trong 'MyObject' mà bạn đang ánh xạ giá trị JSON vào? –

+0

Loại thứ hai, loại trường Java. – monkjack

Trả lời

2

Tôi đã giải quyết được sự cố cụ thể của mình bằng cách thêm triển khai Deserializers vào ObjectMapper. Ví dụ:

Deserializers d = new Deserializers.Base() { 

    @Override 
    public JsonDeserializer<?> findEnumDeserializer(Class<?> type, DeserializationConfig config, BeanDescription beanDesc, BeanProperty property) 
        throws JsonMappingException { 
       if (property.getType().getContentType() != null) 
        return new EnumDeserializer(property.getType().getContentType().getRawClass()); 
       return new EnumDeserializer(property.getType().getRawClass()); 
      } 

     }; 
     mapper.setDeserializerProvider(mapper.getDeserializerProvider().withAdditionalDeserializers(d)); 

Điều này sẽ trả về EnumDeserializer tùy chỉnh của tôi được khởi tạo cho từng loại Enum riêng biệt.

+0

đã cứu tôi một thời gian nhưng imo không sử dụng trình khử mùi enumializer của họ. Tất cả các loại mất giá khủng khiếp, đơn giản hơn để viết của riêng bạn. – MikePatel

+0

Tôi chỉ muốn thêm rằng thiết lập này Deserializers trên api jackson mới là oh quá unholy. ví dụ được cung cấp qua gist: https://gist.github.com/patelm5/9268866 – MikePatel

0

Khoảng nói, và không có ngoại lệ đánh bắt và kiểm tra lỗi ...

JsonToken tok = jp.nextValue(); 

Field field = findField(jp.getCurrentName()); 

Class<?> fc = field.getType(); 

if(fc == int.class) { 
    field.setInt(this, jp.getIntValue()); 
} // handle all the primitive types and String in the same way, then... 
} ... else if(tok == JsonToken.START_ARRAY) { 
    if(fc.isArray()) { 
     // Load into an array 
    } else if(Collection.class.isAssignableFrom(fc)) { 
     // Load into a collection 
    } else { 
     // throw 
    } 
} else if(tok == JsonToken.START_OBJECT) { 
    // Recursively create that object from the JSON stream 
} 

... và vòng lặp cho đến khi tok. là END_OBJECT. Để tìm một lớp học hiện tại theo tên:

Field findField(String name) { 
    for(Class<?> c = getClass(); c != null; c = c.getSuperclass()) { 
     for(Field field : c.getDeclaredFields()) { 
      if(field.getName().equals(name)) { 
       return field; 
      } 
     } 
    } 
} 
+0

Sẽ không tìm thấy nhìn bên trong lớp học của deserializer và không phải là lớp mà deserializer được tạo ra để unmarshall? – monkjack

3

Bạn không - deserializers được đăng ký theo loại, vì vậy bạn cần phải xây dựng deserializer để biết loại dự kiến ​​sẽ deserialize.

Nếu bạn muốn đăng ký bộ khử mùi chung, bạn có thể làm cho mọi thứ năng động hơn bằng cách triển khai ContextualDeserializer. Phương thức createContextual() của nó được gọi với đối số BeanProperty và bạn có thể kiểm tra những thứ như tên của thuộc tính (có thể là null, trong trường hợp giá trị gốc không được tham chiếu bởi thuộc tính) và loại (là loại được khai báo). Phương pháp này sau đó có thể trả về một cá thể mới (KHÔNG sửa đổi deserializer ban đầu, vì nó được chia sẻ bởi tất cả các thuộc tính), được cấu hình với tất cả thông tin bổ sung mà bạn cần.

+0

Đây là một câu trả lời hay, có vẻ như nếu bạn đăng ký một Deserializer với lớp Enum, thì Jackson không nói với lớp tùy chỉnh của bạn, nhưng nó được xây dựng trong enumializer enum. Điều này có nghĩa rằng tôi sẽ phải đăng ký của tôi enumializer enum cusom với mọi loại enum trong các thực thể của tôi. – monkjack

+2

Phải, khi đăng ký deserializers, họ áp dụng cho loại cụ thể bạn đăng ký nó cho.Nếu bạn muốn/cần tạo một cái gì đó để xử lý tất cả các loại enum, bạn sẽ cần phải thay thế 'Deserializers', đăng ký: callback' findEnumDeserializer() 'của nó được gọi mỗi khi một deserializer mới là cần thiết cho một kiểu enum. – StaxMan

+0

Làm cách nào để tạo đối tượng BeanProperty cho lớp mà tôi muốn deserialize? –

0

Tôi đã giải quyết nó như thế này.

Get hiện kiểu trường java ...

@Override 
public Enum deserialize(JsonParser jsonparser, DeserializationContext context) throws IOException, JsonProcessingException { 
    System.out.println("EnumDeserializer ...."); 
    Field field = findField(jsonparser.getCurrentName(), jsonparser.getCurrentValue().getClass()); 
    Class<?> javaType = field.getType(); 
    return null; 
} 

public Field findField(String name, Class<?> c) { 
    for (; c != null; c = c.getSuperclass()) { 
     for (Field field : c.getDeclaredFields()) { 
      if (Modifier.isStatic(field.getModifiers())) { 
       continue; 
      } 
      if (field.getName().equals(name)) { 
       return field; 
      } 
     } 
    } 
    return null; 
}