我有一个要求,根据Majul/unMARCURE Java Pojo的一些元素,根据字段上标注的自定义注释。
假设在我的Java POJP中有3个字段

@CustomVersion("v1")
private String field1;
@CustomVersion("v1","v2")
private String field2;
@CustomVersion("v2")
private String field3;

如果在jaxb中转换时传递version=“v1”参数,我只希望对v1的字段进行marshall。如果我通过了v2,那么所有带有v2注释的字段都应该只被封送处理。
甚至可以使用jaxb吗?我确信选择性编组可以通过某种库或方式得到支持,经过相当长时间的搜索,仍然无法找到它。
我们非常感谢您的帮助、建议或指点。

最佳答案

首先,我建议在编组之前进行这样的预处理。那就容易多了。但是,如果由于某些原因不可能,则可以创建自定义类型适配器。然后,可以对要启用版本控制的每种类型设置@XmlJavaTypeAdapter(VersioningAdapter.class)
@XmlJavaTypeAdapter也可以在包级别指定,但必须指定它应用于哪些类型。如果不指定XmlAdapter,则不能使用@XmlJavaTypeAdapter
这种解决方案的缺点:
如果您有多个版本控制类型,则每个类型都必须用@XmlJavaTypeAdapter
@XmlJavaTypeAdapter不适用于根元素,仅适用于子元素。在封送处理之前,必须在根元素上手动调用适配器
afaik没有其他定制jaxb编组的选项。这就是为什么我认为在封送处理之前,注释处理应该在单独的步骤中执行。除非你能接受上述限制。
适配器示例(完整代码可以找到here):

public class VersioningAdapter extends XmlAdapter<Object, Object> {

    @Override
    public Object unmarshal(Object v) throws Exception {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public Object marshal(Object v) throws Exception {
        if (v == null) {
            return v;
        }
        Field[] fields = v.getClass().getDeclaredFields();
        for (Field field : fields) {
            Annotation[] annotations = field.getDeclaredAnnotations();
            CustomVersion annotation = findCustomVersion(annotations);
            if (annotation != null) {
                if (!contains(annotation, Configuration.getVersion())) {
                    field.setAccessible(true);
                    field.set(v, null);
                }
            }
        }
        return v;
    }

    private CustomVersion findCustomVersion(Annotation[] annotations) {
        for (Annotation annotation : annotations) {
            if (annotation instanceof CustomVersion) {
                return (CustomVersion) annotation;
            }
        }
        return null;
    }

    private boolean contains(CustomVersion annotation, String version) {
        String[] values = annotation.value();
        for (String value : values) {
            if (value.equals(version)) {
                return true;
            }
        }
        return false;
    }

}

10-08 20:24