问题描述
我在这些论坛以及其他博客文章中已经阅读了很多答案,但我似乎无法将各个部分连接起来。
I have read a lot of answers in these forums, as well as other blog posts, but I can't quite seem to connect the pieces together.
所以,我们从包含Map属性的基本POJO开始。已经很好地确定了如何包装它,但这会返回一些值。我要做的是接受name(a.k.a。标签)并使其成为有效的XML'属性'。所以我们会得到一些价值。
So, we start with a basic POJO containing a Map properties. It's well established how to wrap this, but that returns some value. What I'm looking to do is take then name (a.k.a. label) and make it an valid XML 'attribute'. So we would get some value.
我找到了一个例子(如果我能再次找到它会链接)如下:
I found one example (will link if I can find it again) as follows:
@XmlAnyElement
public List<JAXBElement<String>> getXmlProperties() {
List<JAXBElement<String>> elements = new ArrayList<JAXBElement<String>>();
for (Map.Entry<String, String> property: properties.entrySet())
elements.add(new JAXBElement<String>(new QName(property.getKey()),
String.class, property.getValue()));
return elements;
}
这完美无缺,但我在Bean / Pojo类中有这个,与GWT前端共享,因此不能包含对JAXBElement和QName的引用(需要源代码)。
This worked perfectly, but I had this in my Bean/Pojo class, which is shared with a GWT front-end, thus cannot contain references to JAXBElement and QName (source code required).
那么,是否有办法获得类似的结果像XmlAdapter和JAXBElement / QName / XmlAnyElement梦之队?顺便说一句,我正在使用RESTEasy,如果这完全是因素。
So, is there a way to get a similar result using something like the XmlAdapter, and the JAXBElement/QName/XmlAnyElement dream team? By the way, I'm using RESTEasy if that factors in at all.
以下是@ XmlAnyElement + JAXBElement的论坛帖子:
Here is the forum post with the @XmlAnyElement+JAXBElement: Dynamic tag names with JAXB
推荐答案
我的答案并不是那么远 - 经过一些实验后我发现了正确的组合。
I wasn't so far from the answer - after a bit more of experimenting I found the right combo.
创建一个包装类可映射的返回类型。包装器应该包含/ return List< JAXBElement< String>
使用 @XmlAnyElement
注释包装器返回类型。
Create a wrapper class for the un-mapable return type. Wrapper should contain/return List<JAXBElement<String>
Annotate wrapper return type with @XmlAnyElement
.
public class MapWrapper {
@XmlAnyElement
public List<JAXBElement<String>> properties = new ArrayList<JAXBElement<String>>();
}
创建一个封送到MapWrapper的XmlAdapter
Create an XmlAdapter that marshals to the MapWrapper
public class MapAdapter extends XmlAdapter<MapWrapper, Map<String,String>> {
@Override
public MapWrapper marshal(Map<String,String> m) throws Exception {
MapWrapper wrapper = new MapWrapper();
List<JAXBElement<String>> elements = new ArrayList<JAXBElement<String>>();
for (Map.Entry<String, String> property: m.entrySet()) {
elements.add(new JAXBElement<String>(
new QName(getCleanLabel(property.getKey())),
String.class, property.getValue()));
}
wrapper.elements=elements;
return wrapper;
}
@Override
public Map<String,String> unmarshal(MapWrapper v) throws Exception {
// TODO
throw new OperationNotSupportedException();
}
// Return a lower-camel XML-safe attribute
private String getCleanLabel(String attributeLabel) {
attributeLabel = attributeLabel.replaceAll("[()]", "")
.replaceAll("[^\\w\\s]", "_").replaceAll(" ", "_")
.toUpperCase();
attributeLabel = CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL,
attributeLabel);
return attributeLabel;
}
}
使用XmlAdapter注释您的不可映射类型
Annotate your unmappable type with the XmlAdapter
@XmlRootElement
public class SomeBean {
@XmlJavaTypeAdapter(MapAdapter.class)
public LinkedHashMap<String, String> getProperties() {
return properties;
}
}
如下地图:
My Property 1 My Value 1
My Property 2 My Value 2
应该是:
<someBean>
<properties>
<myProperty1>My Value 1</myProperty1>
<myProperty2>My Value 1</myProperty2>
</properties>
</someBean>
希望这有助于其他人!
这篇关于使用JAXB XMLAnyElement类型的样式来返回动态元素名称的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!