Класс сериализации на основе одного интерфейса, который он реализует с Джексоном или Гсоном - PullRequest
4 голосов
/ 19 января 2012

У меня есть следующее:

Интерфейс I1 расширяет Ia, Ib, Ic

Интерфейс I2.

Класс C реализует I1, I2. И у этого класса есть свои собственные сеттеры и геттеры.

C cInstance = new C ():

//Jackson
ObjectMapper mapper = new ObjectMapper();
mapper.writeValue(new File("somefile.json"), cInstance);

//Gson
Gson gson = new Gson();
String json = gson.toJson(cInstance);

Выходные данные будут cInstance сериализованы в соответствии со свойствами C и тем, что он унаследовал. Однако мне нравится, что свойства сериализуются в соответствии с установщиками / получателями в I1 (только свойства cInstance, представленные в интерфейсе I1).

Как я могу сделать это, когда Джексон знает, что у меня слишком много классов с одной и той же проблемой, и я не могу изменить определение класса или добавить аннотации.

То же самое относится и к десериализации (десериализация в соответствии с интерфейсом)

Спасибо

Ответы [ 2 ]

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

Прежде всего, вы всегда можете прикрепить «смешанные аннотации» даже без непосредственного добавления аннотаций (см. вики-страница ). При этом, аннотация для использования будет:

@JsonSerialize(as=MyInterface.class)

но если вы не хотите использовать смешанные модули, вы можете принудительно использовать определенный тип с

objectMapper.typedWriter(MyInterface.class).writeValue(....)
0 голосов
/ 12 мая 2015

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

По крайней мере, это помогает на этапе сериализации.

Вот что я сделал (используя версию 1.9.11 Джексона):

import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.introspect.AnnotatedMethod;
import org.codehaus.jackson.map.introspect.VisibilityChecker;

public static class InterfaceVisibilityChecker extends VisibilityChecker.Std {

    private final Set<Method> visibleMethods;

    public InterfaceVisibilityChecker(Class<?>... clazzes) {
        super(JsonAutoDetect.Visibility.PUBLIC_ONLY);

        this.visibleMethods = new HashSet<>();
        for (Class<?> clz : clazzes) {
            this.visibleMethods.addAll(Arrays.asList(clz.getMethods()));
        }
    }

    @Override
    public boolean isGetterVisible(Method m) {
        return super.isGetterVisible(m) && isVisible(m);
    }

    @Override
    public boolean isGetterVisible(AnnotatedMethod m) {
        return isGetterVisible(m.getAnnotated());
    }

    private boolean isVisible(Method m) {
        for (Method visiMthd : visibleMethods) {
            if (isOverwriteMethod(m, visiMthd)) return true;
        }
        return false;
    }

    private boolean isOverwriteMethod(Method subMethod, Method superMethod) {

        // names must be equal
        if (! subMethod.getName().equals(superMethod.getName())) return false;

        // return types must be assignable
        if (! superMethod.getReturnType().isAssignableFrom(subMethod.getReturnType())) return false;

        // parameters must be equal
        if (! Arrays.equals(subMethod.getParameterTypes(), superMethod.getGenericParameterTypes())) return false;

        // classes must be assignable
        return superMethod.getDeclaringClass().isAssignableFrom(subMethod.getDeclaringClass());
    }
}

Основная идея заключается в использованиистандарт VisibilityChecker и расширить его путем проверки, объявлен ли метод в одном из заданных интерфейсов.

Средство проверки применяется к экземпляру ObjectMapper с использованием следующего фрагмента:

ObjectMapper om = new ObjectMapper();
om.setVisibilityChecker(new InterfaceVisibilityChecker(
     I1.class, 
     I2.class, 
     Ia.class, 
     Ib.class, 
     Ic.class

));

Некоторые комментарии к решению выше:

  1. Проверка не завершена, такие методы, как isIsGetterVisible или isFieldVisible, могут обрабатываться аналогичным образом, если это необходимо..
  2. isOverwriteMethod вообще не оптимизирован, его проверки могут быть кэшированы.
...