使用 JAXB XMLAnyElement 类型的样式返回动态元素名称

sha*_*son 2 java jaxb resteasy

我在这些论坛以及其他博客文章中阅读了很多答案,但我似乎无法将这些部分联系在一起。

因此,我们从一个包含 Map 属性的基本 POJO 开始。如何包装它已经很好地确定了,但这会返回一些值。我要做的是取然后名称(又名标签)并使其成为有效的 XML“属性”。所以我们会得到一些价值。

我找到了一个例子(如果我能再次找到它会链接)如下:

@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;
}
Run Code Online (Sandbox Code Playgroud)

这工作得很好,但我在我的 Bean/Pojo 类中有这个,它与 GWT 前端共享,因此不能包含对 JAXBElement 和 QName 的引用(需要源代码)。

那么,有没有办法使用 XmlAdapter 和 JAXBElement/QName/XmlAnyElement 梦之队之类的东西来获得类似的结果?顺便说一句,如果考虑到这些因素,我正在使用 RESTEasy。

这是带有@XmlAnyElement+JAXBElement 的论坛帖子: Dynamic tag names with JAXB

sha*_*son 5

我离答案不远了 - 经过更多的实验,我找到了正确的组合。

为不可映射的返回类型创建一个包装类。包装器应包含/返回List<JAXBElement<String>带有@XmlAnyElement.

public class MapWrapper {
   @XmlAnyElement
    public List<JAXBElement<String>> properties = new ArrayList<JAXBElement<String>>();
}
Run Code Online (Sandbox Code Playgroud)

创建一个编组到 MapWrapper 的 XmlAdapter

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;
}
}
Run Code Online (Sandbox Code Playgroud)

使用 XmlAdapter 注释不可映射的类型

@XmlRootElement
public class SomeBean {

    @XmlJavaTypeAdapter(MapAdapter.class)
    public LinkedHashMap<String, String> getProperties() {
        return properties;
    }
}
Run Code Online (Sandbox Code Playgroud)

像这样的地图:

My Property 1    My Value 1 
My Property 2    My Value 2
Run Code Online (Sandbox Code Playgroud)

应该是这样的:

<someBean>
   <properties>
     <myProperty1>My Value 1</myProperty1>
     <myProperty2>My Value 1</myProperty2>
   </properties>
</someBean>
Run Code Online (Sandbox Code Playgroud)

希望这对其他人有帮助!