How to map a nested XML element content as a string of a map?

43 Views Asked by At

I'm using Java and Jackson:

<dependency>
    <groupId>com.fasterxml.jackson.dataformat</groupId>
    <artifactId>jackson-dataformat-xml</artifactId>
    <version>2.8.7</version>
</dependency>

I have this XML and want to deserialize the element name: <RandomName> (note that this element name can be anything and the content of it is random as well) as the key and any XML content under it as the string value of a map, so it would be like: RandomName -> <metadaten> ... </metadaten>.

<slices>
    <slice>
        <boundedBy>
            <Envelope>
                <axisLabels>Lat Long</axisLabels>
                <srsDimension>2</srsDimension>
                <lowerCorner>-44.975 111.975</lowerCorner>
                <upperCorner>-8.975 130.975</upperCorner>
            </Envelope>
        </boundedBy>
        <local_metadata_key>test123</local_metadata_key>
        <RandomName>
            <metadaten>
                <Kompression>0</Kompression>
                <Komprimierung>0</Komprimierung>
                <Belaubungszustand>3</Belaubungszustand>
                <Bemerkungen>keine</Bemerkungen>
            </metadaten>
        </RandomName>
        <fileReferenceHistory>testfile</fileReferenceHistory>   
    </slice>
</slices>

I have this class to deserialize the XML to it, but in the method addKeyValue(), it always sees key = RandomName and value = empty string, here I wanted, value = <metadaten> ... </metadaten> instead.

public class LocalMetadataChild {
    
    public static final String LOCAL_METADATA_TAG = "slice";

    private Map<String, String> localMetadataAttributesMap;
    
    private BoundedBy boundedBy;

    @JsonAnySetter
    // NOTE: To map an unknown list of properties, must use this annotation
    public void addKeyValue(String key, String value) {
        this.localMetadataAttributesMap.put(key, value);
    }

    public LocalMetadataChild() {
        this.localMetadataAttributesMap = new LinkedHashMap<>();
        this.boundedBy = new BoundedBy();
    }

    @JsonAnyGetter
    // NOTE: to unwrap the "map" from { "map": { "key": "value" } }, only keep { "key": "value" }
    public Map<String, String> getLocalMetadataAttributesMap() {
        return localMetadataAttributesMap;
    }
    
    public BoundedBy getBoundedBy() {
        return this.boundedBy;
    }

    public void setBoundedBy(BoundedBy boundedBy) {
        this.boundedBy = boundedBy;
    }

    public LocalMetadataChild(Map<String, String> localMetadataAttributesMap, BoundedBy boundedBy) {
        this.localMetadataAttributesMap = localMetadataAttributesMap;
        this.boundedBy = boundedBy;
    }
}
1

There are 1 best solutions below

0
On

Ok, it is actually easier than I thought, Jackson is awesome.

Just need to change type from String for value to type Object like below:

private Map<String, Object> localMetadataAttributesMap;
    
    private BoundedBy boundedBy;

    @JsonAnySetter
    // NOTE: To map an unknown list of properties, must use this annotation
    public void addKeyValue(String key, Object value) {
        this.localMetadataAttributesMap.put(key, value);
    }

    public LocalMetadataChild() {
        this.localMetadataAttributesMap = new LinkedHashMap<>();
        this.boundedBy = new BoundedBy();
    }

    @JsonAnyGetter
    // NOTE: to unwrap the "map" from { "map": { "key": "value" } }, only keep { "key": "value" }
    public Map<String, Object> getLocalMetadataAttributesMap() {
        return localMetadataAttributesMap;
    }

Then, serialize the value to String afterwards.

        XmlMapper xmlMapper = new XmlMapper();
        Object obj = value of the map above
        xmlMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        xmlMapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
        String xml = xmlMapper.writer().writeValueAsString(obj);