Настраиваемый десериализатор Джексона, получающий доступ к текущему классу поля - PullRequest
7 голосов
/ 20 января 2012

Я пытаюсь написать собственный десериализатор для Джексона и хочу сделать его универсальным (универсальным в смысле работы над любым типом, а не как в «универсальных»).

Однако я не могу понять, как определить тип десериализованного поля.

Например, я ищу что-то вроде следующего:

@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 ]

3 голосов
/ 21 января 2012

Вы не - десериализаторы регистрируются по типу, поэтому вам нужно создать десериализатор, чтобы знать, какой тип он должен десериализовать.

Если вы хотите зарегистрировать универсальный десериализатор, вы можете, однако,сделать вещи более динамичными, внедрив ContextualDeserializer.Его createContextual() метод вызывается с аргументом BeanProperty, и вы можете проверить такие вещи, как имя свойства (которое может быть нулевым, в случае корневых значений, на которые свойство не ссылается) и тип (который является объявленным типом).Затем этот метод может вернуть новый экземпляр (НЕ изменяйте исходный десериализатор, так как он является общим для всех свойств), настроенный со всей необходимой дополнительной информацией.

2 голосов
/ 23 января 2012

Я решил свою конкретную проблему, добавив реализацию десериализаторов в 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));

Это вернет мой пользовательский EnumDeserializer, созданный для каждого отдельного типа Enum.

0 голосов
/ 14 октября 2016

Я решил это так.

Получить текущее поле типа 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;
}

0 голосов
/ 20 января 2012

Грубо говоря, без исключения перехвата и проверки ошибок ...

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;
            }
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...