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

Java 使用样式的JAXB XMLAnyElement类型返回动态元素名称,java,jaxb,resteasy,Java,Jaxb,Resteasy,我在这些论坛上读到了很多答案,还有其他的博客文章,但我似乎无法将这些部分联系起来 因此,我们从包含映射属性的基本POJO开始。已经确定了如何包装它,但这会返回一些值。我要做的是获取then名称(又称标签),并使其成为有效的XML“属性”。所以我们会得到一些价值 我发现了一个示例(如果我能再次找到它,将链接),如下所示: @XmlAnyElement public List<JAXBElement<String>> getXmlProperties() { List&

我在这些论坛上读到了很多答案,还有其他的博客文章,但我似乎无法将这些部分联系起来

因此,我们从包含映射属性的基本POJO开始。已经确定了如何包装它,但这会返回一些值。我要做的是获取then名称(又称标签),并使其成为有效的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;
}
@xmlanyement
公共列表getXmlProperties(){
列表元素=新的ArrayList();
对于(Map.Entry属性:properties.entrySet())
添加(新的JAXBElement(新的QName(property.getKey()),
String.class,property.getValue());
返回元素;
}
这工作得很好,但我在Bean/Pojo类中使用了它,该类与GWT前端共享,因此不能包含对JAXBElement和QName的引用(需要源代码)

那么,有没有一种方法可以使用XmlAdapter和JAXBElement/QName/XmlAnyElement dream团队之类的东西获得类似的结果?顺便说一下,如果考虑到这一点,我正在使用RESTEasy


这是一篇关于@xmlanyement+JAXBElement的论坛帖子:

我离答案不远了——经过一点实验,我找到了正确的组合


为不可映射的返回类型创建包装器类。包装器应该包含/return
List我离答案不远了——经过更多的实验,我找到了正确的组合


为不可映射的返回类型创建包装器类。包装器应该包含/return
List取决于上面列出的解决方案,我参与了这个
MapAdapter
处理封送和反封送过程

@XmlType
public class MapWrapper{
    private List<JAXBElement<String>> properties = new ArrayList<>();

    public MapWrapper(){

    }
    @XmlAnyElement
    public List<JAXBElement<String>> getProperties() {
        return properties;
    }
    public void setProperties(List<JAXBElement<String>> properties) {
        this.properties = properties;
    }
    @Override
    public String toString() {
        return "MapWrapper [properties=" + toMap() + "]";
    }


    public Map<String, String> toMap(){
        //Note: Due to type erasure, you cannot use properties.stream() directly when unmashalling is used.
        List<?> props = properties;
        return props.stream().collect(Collectors.toMap(MapWrapper::extractLocalName, MapWrapper::extractTextContent));
    }

    @SuppressWarnings("unchecked")
    private static String extractLocalName(Object obj){

        Map<Class<?>, Function<? super Object, String>> strFuncs = new HashMap<>();
        strFuncs.put(JAXBElement.class, (jaxb) -> ((JAXBElement<String>)jaxb).getName().getLocalPart());
        strFuncs.put(Element.class, ele -> ((Element) ele).getLocalName());
        return extractPart(obj, strFuncs).orElse("");
    }


    @SuppressWarnings("unchecked")
    private static String extractTextContent(Object obj){
        Map<Class<?>, Function<? super Object, String>> strFuncs = new HashMap<>();
        strFuncs.put(JAXBElement.class, (jaxb) -> ((JAXBElement<String>)jaxb).getValue());
        strFuncs.put(Element.class, ele -> ((Element) ele).getTextContent());
        return extractPart(obj, strFuncs).orElse("");
    }

    private static <ObjType, T> Optional<T> extractPart(ObjType obj, Map<Class<?>, Function<? super ObjType, T>> strFuncs){
        for(Class<?> clazz : strFuncs.keySet()){
            if(clazz.isInstance(obj)){
                return Optional.of(strFuncs.get(clazz).apply(obj));
            }
        }
        return Optional.empty();
    }
}

public class MapAdapter extends XmlAdapter<MapWrapper, Map<String, String>>{

    @Override
    public Map<String, String> unmarshal(MapWrapper v) throws Exception {
        return v.toMap();
    }

    @Override
    public MapWrapper marshal(Map<String, String> m) throws Exception {
        MapWrapper wrapper = new MapWrapper();

        for(Map.Entry<String, String> entry : m.entrySet()){
             wrapper.addEntry(new JAXBElement<String>(new QName(entry.getKey()), String.class, entry.getValue()));
        }

        return wrapper;
    }

}
@XmlType
公共类映射包装器{
私有列表属性=新的ArrayList();
公共映射包装器(){
}
@XmlAnyElement
公共列表getProperties(){
归还财产;
}
公共void集合属性(列表属性){
这个。属性=属性;
}
@凌驾
公共字符串toString(){
返回“MapWrapper[properties=“+toMap()+”]”;
}
公共地图toMap(){
//注意:由于类型擦除,在使用Unshalling时不能直接使用properties.stream()。
列出道具=属性;
返回props.stream().collect(Collectors.toMap(MapWrapper::extractLocalName,MapWrapper::extractTextContent));
}
@抑制警告(“未选中”)
私有静态字符串extractLocalName(对象obj){

Map,Function取决于上面列出的解决方案,我加入了这个
MapAdapter
,它同时处理封送和解封送过程

@XmlType
public class MapWrapper{
    private List<JAXBElement<String>> properties = new ArrayList<>();

    public MapWrapper(){

    }
    @XmlAnyElement
    public List<JAXBElement<String>> getProperties() {
        return properties;
    }
    public void setProperties(List<JAXBElement<String>> properties) {
        this.properties = properties;
    }
    @Override
    public String toString() {
        return "MapWrapper [properties=" + toMap() + "]";
    }


    public Map<String, String> toMap(){
        //Note: Due to type erasure, you cannot use properties.stream() directly when unmashalling is used.
        List<?> props = properties;
        return props.stream().collect(Collectors.toMap(MapWrapper::extractLocalName, MapWrapper::extractTextContent));
    }

    @SuppressWarnings("unchecked")
    private static String extractLocalName(Object obj){

        Map<Class<?>, Function<? super Object, String>> strFuncs = new HashMap<>();
        strFuncs.put(JAXBElement.class, (jaxb) -> ((JAXBElement<String>)jaxb).getName().getLocalPart());
        strFuncs.put(Element.class, ele -> ((Element) ele).getLocalName());
        return extractPart(obj, strFuncs).orElse("");
    }


    @SuppressWarnings("unchecked")
    private static String extractTextContent(Object obj){
        Map<Class<?>, Function<? super Object, String>> strFuncs = new HashMap<>();
        strFuncs.put(JAXBElement.class, (jaxb) -> ((JAXBElement<String>)jaxb).getValue());
        strFuncs.put(Element.class, ele -> ((Element) ele).getTextContent());
        return extractPart(obj, strFuncs).orElse("");
    }

    private static <ObjType, T> Optional<T> extractPart(ObjType obj, Map<Class<?>, Function<? super ObjType, T>> strFuncs){
        for(Class<?> clazz : strFuncs.keySet()){
            if(clazz.isInstance(obj)){
                return Optional.of(strFuncs.get(clazz).apply(obj));
            }
        }
        return Optional.empty();
    }
}

public class MapAdapter extends XmlAdapter<MapWrapper, Map<String, String>>{

    @Override
    public Map<String, String> unmarshal(MapWrapper v) throws Exception {
        return v.toMap();
    }

    @Override
    public MapWrapper marshal(Map<String, String> m) throws Exception {
        MapWrapper wrapper = new MapWrapper();

        for(Map.Entry<String, String> entry : m.entrySet()){
             wrapper.addEntry(new JAXBElement<String>(new QName(entry.getKey()), String.class, entry.getValue()));
        }

        return wrapper;
    }

}
@XmlType
公共类映射包装器{
私有列表属性=新的ArrayList();
公共映射包装器(){
}
@XmlAnyElement
公共列表getProperties(){
归还财产;
}
公共void集合属性(列表属性){
这个。属性=属性;
}
@凌驾
公共字符串toString(){
返回“MapWrapper[properties=“+toMap()+”]”;
}
公共地图toMap(){
//注意:由于类型擦除,在使用Unshalling时不能直接使用properties.stream()。
列出道具=属性;
返回props.stream().collect(Collectors.toMap(MapWrapper::extractLocalName,MapWrapper::extractTextContent));
}
@抑制警告(“未选中”)
私有静态字符串extractLocalName(对象obj){

Map,function你救了我一天!谢谢:)如果你添加了unmarshall函数那就太好了hi,非常感谢你的回复。我正在尝试unmarshal
XML
,我不知道如何在这里实现
unmarshal
方法。如果可能的话,你能为我提到的
unmarshal
方法提供示例吗在
MapAdapter
类中:您救了我一天!谢谢:)如果您添加了解组功能,那就太好了。hi,非常感谢您的响应。我正在尝试解组
XML
,我不知道如何在这里实现
unmarshal
方法。如果可能,请您提供
unmarshal的示例MapAdapter
类中提到的code>方法:这在现实生活中是如何使用的?很高兴看到一个例子!这在现实生活中是如何使用的?很高兴看到一个例子!
@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>
@XmlType
public class MapWrapper{
    private List<JAXBElement<String>> properties = new ArrayList<>();

    public MapWrapper(){

    }
    @XmlAnyElement
    public List<JAXBElement<String>> getProperties() {
        return properties;
    }
    public void setProperties(List<JAXBElement<String>> properties) {
        this.properties = properties;
    }
    @Override
    public String toString() {
        return "MapWrapper [properties=" + toMap() + "]";
    }


    public Map<String, String> toMap(){
        //Note: Due to type erasure, you cannot use properties.stream() directly when unmashalling is used.
        List<?> props = properties;
        return props.stream().collect(Collectors.toMap(MapWrapper::extractLocalName, MapWrapper::extractTextContent));
    }

    @SuppressWarnings("unchecked")
    private static String extractLocalName(Object obj){

        Map<Class<?>, Function<? super Object, String>> strFuncs = new HashMap<>();
        strFuncs.put(JAXBElement.class, (jaxb) -> ((JAXBElement<String>)jaxb).getName().getLocalPart());
        strFuncs.put(Element.class, ele -> ((Element) ele).getLocalName());
        return extractPart(obj, strFuncs).orElse("");
    }


    @SuppressWarnings("unchecked")
    private static String extractTextContent(Object obj){
        Map<Class<?>, Function<? super Object, String>> strFuncs = new HashMap<>();
        strFuncs.put(JAXBElement.class, (jaxb) -> ((JAXBElement<String>)jaxb).getValue());
        strFuncs.put(Element.class, ele -> ((Element) ele).getTextContent());
        return extractPart(obj, strFuncs).orElse("");
    }

    private static <ObjType, T> Optional<T> extractPart(ObjType obj, Map<Class<?>, Function<? super ObjType, T>> strFuncs){
        for(Class<?> clazz : strFuncs.keySet()){
            if(clazz.isInstance(obj)){
                return Optional.of(strFuncs.get(clazz).apply(obj));
            }
        }
        return Optional.empty();
    }
}

public class MapAdapter extends XmlAdapter<MapWrapper, Map<String, String>>{

    @Override
    public Map<String, String> unmarshal(MapWrapper v) throws Exception {
        return v.toMap();
    }

    @Override
    public MapWrapper marshal(Map<String, String> m) throws Exception {
        MapWrapper wrapper = new MapWrapper();

        for(Map.Entry<String, String> entry : m.entrySet()){
             wrapper.addEntry(new JAXBElement<String>(new QName(entry.getKey()), String.class, entry.getValue()));
        }

        return wrapper;
    }

}