2012-01-19 6 views
4

я следующее:класс Serialize основанный на одном интерфейсе он реализует с Джексоном или Gson

интерфейс I1 проходит Ia, Ib, Ic

интерфейс I2.

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

С cInstance = новый С():

//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

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

@JsonSerialize(as=MyInterface.class) 

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

objectMapper.typedWriter(MyInterface.class).writeValue(....) 
+0

ссылка не работает – Kaan

+0

Извините, что, спасибо за отчетность, исправлено. – StaxMan

+0

Это должно быть @JsonSerialize (as = MyInterface.class), но, к сожалению, это не работает для меня в jackson 2.1.1. Атрибут using предназначен для указания реализации JsonSerializer. –

0

Джексон 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 не оптимизирован вообще, его чеки могут быть кэшированы.