定制杰克逊解串器获得当前现场类的访问权限

时间:2012-01-20 15:50:45

标签: java deserialization jackson

我正在尝试为杰克逊编写一个自定义反序列化程序,我想让它变得通用(在任何类型的意义上都是通用的,而不是在“泛型”中)。

但是我似乎无法弄清楚如何处理被反序列化的字段的类型。

例如,我正在寻找以下内容:

@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);
}

具体是获取当前字段的类型部分,我一直在努力。

编辑:这是我感兴趣的java字段的类型。

4 个答案:

答案 0 :(得分:3)

您没有 - 反序列化器按类型注册,因此您需要构建反序列化器以了解预期反序列化的类型。

如果您确实想要注册通用反序列化器,则可以通过实现ContextualDeserializer来使事物更具动态性。使用createContextual()参数调用其BeanProperty方法,您可以检查属性名称(如果属性未引用的根值,则可能为null)和类型(是声明的类型)。 然后,此方法可以返回一个新实例(不要修改原始反序列化器,因为它由所有属性共享),并配置了您需要的所有额外信息。

答案 1 :(得分:2)

我通过向ObjectMapper添加反序列化器的实现来解决我的特殊问题。例如

   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));

这将返回为每个单独的Enum类型实例化的自定义EnumDeserializer。

答案 2 :(得分:0)

粗略地说,无一例外地捕捉和错误检查......

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
}

...并循环直到tok为END_OBJECT。要按名称查找当前类:

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;
            }
        }
    }
}

答案 3 :(得分:0)

我这样解决了。

获取当前字段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;
}