如何在解析XML时使XStream跳过未映射的标记?
我有一个很大的XML文档,我想转换为一个Java bean。它有很多标签和属性,但我只对其中的一小部分感兴趣。不言而喻,XStream似乎强迫你在该bean中为每个可能在该XML中的标记声明一个属性。有没有解决的办法?如何在解析XML时使XStream跳过未映射的标记?
如下所示初始化XStream
,忽略bean中未定义的字段。
XStream xstream = new XStream() {
@Override
protected MapperWrapper wrapMapper(MapperWrapper next) {
return new MapperWrapper(next) {
@Override
public boolean shouldSerializeMember(Class definedIn, String fieldName) {
if (definedIn == Object.class) {
return false;
}
return super.shouldSerializeMember(definedIn, fieldName);
}
};
}
};
我一直在工作我的方式解决这个问题,今天我所发现的是,使用return this.realClass(fieldName) != null;
不是(总是)工作解决方案但实际上没有用于XStream的跳过未映射的方式标记并同时处理隐式集合。
为什么realClass(fieldName)
事情将无法正常工作
事实上招用
try {
return this.realClass(fieldName) != null;
} catch (Throwable t) {
return false;
}
作品。它所做的是尝试通过标记名称来猜测类型,看它是否成功,如果不成功 - 返回false。所以它会完全跳过标签,如
<someUnknownTag>someContent</someUnknownTag>
但它会工作最多只能到时间(!)时不知何故一些“不需要”的标签会碰巧有一个有意义的名字为其realClass(fieldName)
将实际能够返回不等于null
的东西,并且该标记不会是您的任何ImplicitCollection的成员。在这种情况下,知道可以定义xml元素的类,并且在用户类型XStream中不存在这样的字段映射将决定“也许这个元素来自某些隐式集合”。如果班上既没有这样的集合,也没有一个领域,它很快就会失败。在我的情况下,有问题的一段XML是这样的:
<url>http://somewhere.com</url>
,当然,还有我的类既不Url url;
也不@XStreamImplicit List<Url> url
。具有这样的XML和使用的结果“realClass”东西如下:
com.thoughtworks.xstream.converters.ConversionException: Element url of type java.net.URL is not defined as field in type org.sample.xstream.SomeBean
正确的方式
正确的方式将从shouldSerializeMember
万一当definedIn == Object.class
(不使用被返回平原false
realClass(fieldName)
东西)。
但仅仅使用return false
是不够的。我这种形式会导致XStream将隐式集合留空。
这里的诀窍是确保使用@XStreamImplicit(itemFieldName = "something")
而不是仅使用@XStreamImplicit
而不带参数,即使在标签名称和集合的通用参数类型具有相同名称的情况下。
所以正确的代码如下所示:
xstream = new XStream() {
@Override
protected MapperWrapper wrapMapper(MapperWrapper next) {
return new MapperWrapper(next) {
@Override
public boolean shouldSerializeMember(Class definedIn, String fieldName) {
if (definedIn == Object.class) {
//This is not compatible with implicit collections where item name is not defined
return false;
} else {
return super.shouldSerializeMember(definedIn, fieldName);
}
}
};
}
};
xsteam.processAnnotations(SomeRootEntry.class);
而且你必须确保在您的类的隐式集合标记是这样的:
@XStreamImplicit(itemFieldName = "something")
private List <Something> somethingList;
注意itemFieldName
是明确即使List的泛型类型参数具有相同的名称也是如此。这是至关重要的。
在这种情况下遇到<something>
标签XStream甚至不会使用该fieldName访问您的shouldSerializeMember
。它将事先知道元素来自隐式集合。
当它将访问您的方法是再次遇到<url>http://somewhere.com</url>
。但在这里我们很安全,因为我们只返回false
。
适合我!试一试。
XStream的1.4.5 durring编组声明它足以使用ignoreEnknownElements()方法:
XStreamMarshaller marshaller = new XStreamMarshaller();
marshaller.getXStream().ignoreUnknownElements();
...
忽略不必要的元素。
对集合使用@XStreamImplicit注解时,这不起作用。有任何想法吗? – 2011-12-20 21:11:42
使用@ com.thoughtworks.xstream.annotations.XStreamOmitField – timomeinen 2013-01-18 11:15:25
XStreamOmitField不适用于我!没有XStream文档中提到的瞬态。 – endless 2013-05-03 21:42:57