Существует еще один подход к решению этой проблемы более обобщенно для объектов, которые должны быть десериализованы с использованием BeanDeserializer, создав BeanDeserializerModifier
и зарегистрировав его в своем картографическом устройстве.BeanDeserializerModifier
является своего рода альтернативой подклассу BeanDeserializerFactory
и дает вам возможность вернуть что-то отличное от обычного десериализатора или изменить его.
Итак, сначала создайте новый JsonDeserializer
, который может принимать другой десериализатор при его создании, а затем удерживает этот сериализатор.В методе десериализации вы можете проверить, передали ли вы JsonParser
, который в данный момент указывает на JsonToken.START_ARRAY
.Если вы не прошли JsonToken.START_ARRAY
, просто используйте десериализатор по умолчанию, который был передан этой пользовательской десериализации при ее создании.
Наконец, убедитесь, что реализован ResolvableDeserializer
, чтобы десериализатор по умолчанию был правильно подключен к контексту, который использует ваш пользовательский десериализатор.
class ArrayAsNullDeserialzer extends JsonDeserializer implements ResolvableDeserializer {
JsonDeserializer<?> mDefaultDeserializer;
@Override
/* Make sure the wrapped deserializer is usable in this deserializer's contexts */
public void resolve(DeserializationContext ctxt) throws JsonMappingException {
((ResolvableDeserializer) mDefaultDeserializer).resolve(ctxt);
}
/* Pass in the deserializer given to you by BeanDeserializerModifier */
public ArrayAsNullDeserialzer(JsonDeserializer<?> defaultDeserializer) {
mDefaultDeserializer = defaultDeserializer;
}
@Override
public Object deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
JsonToken firstToken = jp.getCurrentToken();
if (firstToken == JsonToken.START_ARRAY) {
//Optionally, fail if this is something besides an empty array
return null;
} else {
return mDefaultDeserializer.deserialize(jp, ctxt);
}
}
}
Теперь, когда у нас есть универсальный десериализатор, давайте создадим модификатор, который сможет его использовать.Это просто, просто реализуйте метод modifyDeserializer
в вашем BeanDeserializerModifier.Вам передадут десериализатор, который будет использован для десериализации бина.Он также передает вам BeanDesc, который будет десериализован, так что вы можете здесь контролировать, хотите ли вы обрабатывать [] как ноль для всех типов.
public class ArrayAsNullDeserialzerModifier extends BeanDeserializerModifier {
@Override
public JsonDeserializer<?> modifyDeserializer(DeserializationConfig config, BeanDescription beanDesc, JsonDeserializer<?> deserializer) {
if ( true /* or check beanDesc to only do this for certain types, for example */ ) {
return new ArrayAsNullDeserializer(deserializer);
} else {
return deserializer;
}
}
}
Наконец, вам нужно зарегистрировать свой BeanDeserializerModifier в ObjectMapper.Чтобы сделать это, создайте модуль и добавьте модификатор в настройку (к сожалению, SimpleModules, похоже, не имеют зацепки для этого).Вы можете прочитать больше о модулях в другом месте, но вот пример, если у вас еще нет модуля для добавления:
Module m = new Module() {
@Override public String getModuleName() { return "MyMapperModule"; }
@Override public Version version() { return Version.unknownVersion(); }
@Override public void setupModule(Module.SetupContext context) {
context.addBeanDeserializerModifier(new ArrayAsNullDeserialzerModifier());
}
};