Custom BeanPropertyFilter - только сериализация части строки
Я остро нуждаюсь в помощи. В настоящее время я делаю некоторые ограничения безопасности для ресурса в Content API, где мне нужно либо: включить свойства, усечь свойства (если они являются String.class) или удалить свойства из объекта сериализации на основе SecurityContext.
Я использую Джексона как мой сериализатор json и решил использовать BeanPropertyFilter, чтобы проверить, должно ли каждое свойство быть сериализованным или нет.
Теперь параметры удаления и включения довольно просты: я сериализую компонент или нет.
Но вариант усечения немного хуже. Итак, вот что я сделал до сих пор в отношении сериализации свойства.
@Override
public void serializeAsField(Object bean, JsonGenerator jgen, SerializerProvider provider, BeanPropertyWriter writer) throws Exception {
switch (determineFilterAction(writer)) {
case INCLUDE_UNMODIFIED:
writer.serializeAsField(bean, jgen, provider);
break;
case INCLUDE_TRUNCATED:
Object value = writer.get(bean);
if (!(value instanceof String)) {
throw new UnsupportedOperationException("Annotation indicates truncate on " + writer.toString() + " which is not a string, but a " + value.getClass().getSimpleName() + " and is unsupported");
}
JsonSerializer oldSerialzer= writer.getSerializer();
writer.assignSerializer(new TruncateStringJsonSerializer());
writer.serializeAsField(bean, jgen, provider);
writer.assignSerializer(oldSerialzer);
break;
case REMOVE:
// do nothing
break;
}
}
Проблема в том, что в методе BeanPropertyWriter.assignSerializer() есть защита, которая не позволяет мне переключать новый настраиваемый сериализатор для этого одного свойства.
Есть ли способ подключиться и изменить значение бина? Или мне придется переопределить фабрики и BeanPropertyWriter, чтобы переопределить метод assignSerializer () (чтобы избежать защиты сериализатора)?
Я не могу просто аннотировать свои свойства с помощью специального средства записи, поскольку объект сериализации ничего не знает о SecurityContext, поэтому нет способа внедрить securityContext в пользовательский сериализатор.
Есть ли какой-нибудь способ сделать этот вариант усечения (не делая его слишком хакерским)?
Заранее спасибо.
// С наилучшими пожеланиями, Мартин.
ОБНОВИТЬ
Основываясь на ответе StaxMan, я обновил метод, чтобы он выглядел следующим образом, и, похоже, он работает. По крайней мере, все мои тесты выполняются правильно. Далее будем тестировать на разработке приложений-серверов.
@Override
public void serializeAsField(Object bean, JsonGenerator jgen, SerializerProvider provider, BeanPropertyWriter writer) throws Exception {
switch (determineFilterAction(writer)) {
case INCLUDE_UNMODIFIED:
writer.serializeAsField(bean, jgen, provider);
break;
case INCLUDE_TRUNCATED:
Object value = writer.get(bean);
if (!(value instanceof String)) {
throw new UnsupportedOperationException("Annotation indicates truncate on " + writer.toString() + " which is not a string, but a " + value.getClass().getSimpleName() + " and is unsupported");
}
String valueString = (String) value;
jgen.writeFieldName(writer.getName());
jgen.writeString(StringUtils.abbreviate(valueString, MAX_LENGTH));
break;
case REMOVE:
// do nothing
break;
}
}
1 ответ
Нет, даже не пытайся позвонить assignSerializer
Это плохая идея в многопоточной среде - есть только один экземпляр этого сериализатора, и даже если бы вы могли его вызвать, он просто вызвал бы странное исключение в случаях, когда две сериализации выполнялись одновременно.
Но, возможно, вам следует рассмотреть этот подход с другой стороны: поскольку вы уже находите String
значение, почему бы не записать усеченное значение напрямую, используя JsonGenerator
? Или, если вы предпочитаете, делегируйте что-то, что делает запись; но так как вы называете это, это не должно быть JsonSerializer
или что-нибудь.