基于它与Jackson或Gson实现的一个接口来序列化类

时间:2012-01-19 07:13:49

标签: serialization jackson deserialization gson

我有以下内容:

接口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);

输出将根据C的属性及其继承的内容序列化cInstance。 但是,我喜欢将属性序列化为根据I1中的setter / getter(仅在I1接口中表示的cInstance属性)。

我怎么能和杰克逊知道我有太多类有相同问题的课程,而且我无法修改课程定义或添加注释。

同样的问题适用于反序列化(根据接口反序列化)

由于

2 个答案:

答案 0 :(得分:3)

首先,即使不直接添加注释,也可以随时附加“混合注释”(参见wiki page)。有了这个,使用的注释将是:

@JsonSerialize(as=MyInterface.class)

但如果您不想使用混合,可以强制使用特定类型

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

答案 1 :(得分: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. 检查工具不完整,如果需要,可以采用类似方式处理isIsGetterVisibleisFieldVisible等方法。
  2. isOverwriteMethod根本没有优化,它的检查可以缓存。