Use JAXB XMLAnyElement type of style to return dynamic element names

前端 未结 2 1556
悲&欢浪女
悲&欢浪女 2020-12-18 14:02

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.

So, we start with a basic POJO con

2条回答
  •  悲哀的现实
    2020-12-18 14:37

    I wasn't so far from the answer - after a bit more of experimenting I found the right combo.

    Create a wrapper class for the un-mapable return type. Wrapper should contain/return List Annotate wrapper return type with @XmlAnyElement.

    public class MapWrapper {
       @XmlAnyElement
        public List> properties = new ArrayList>();
    }
    

    Create an XmlAdapter that marshals to the MapWrapper

    public class MapAdapter extends XmlAdapter> {
        @Override
        public MapWrapper marshal(Map m) throws Exception {
        MapWrapper wrapper = new MapWrapper();
        List> elements = new ArrayList>();
           for (Map.Entry property: m.entrySet()) {
              elements.add(new JAXBElement(
                        new QName(getCleanLabel(property.getKey())), 
              String.class, property.getValue()));
           }
           wrapper.elements=elements;
        return wrapper;
    }
    
    @Override
    public Map 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;
    }
    }
    

    Annotate your unmappable type with the XmlAdapter

    @XmlRootElement
    public class SomeBean {
    
        @XmlJavaTypeAdapter(MapAdapter.class)
        public LinkedHashMap getProperties() {
            return properties;
        }
    }
    

    A map like:

    My Property 1    My Value 1 
    My Property 2    My Value 2
    

    Should come out as:

    
       
         My Value 1
         My Value 1
       
    
    

    Hope this helps someone else!

提交回复
热议问题