我有一个要求,根据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;
}
}