3

using Eclipselink MOXy, I have the following class:

@XmlAccessorType(XmlAccessType.PUBLIC_MEMBER)
@XmlType(name = "")
public class MyObject {
  private Map<String, String> meta;

  @XmlPath(".")
  @XmlJavaTypeAdapter(MetaMapAdapter.class)
  public Map<String, String> getMeta() {
    return meta;
  }

  public setMeta(Map<String, String> m) {
    meta = m;
  }
}

My AdaptedMap looks like this (credits to JAXB: how to marshall map into <key>value</key>):

import javax.xml.bind.annotation.XmlAnyElement;

public class AdaptedMap {
    private Object value;
    public AdaptedMap() {}
    @XmlAnyElement
    public Object getValue() { return value; }
    public void setValue(final Object value) { this.value = value; }
}

And the MapAdapter looks like this (credits to JAXB: how to marshall map into <key>value</key>):

import java.util.*;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import javax.xml.parsers.*;
import org.eclipse.persistence.oxm.XMLRoot;
import org.w3c.dom.*;

public class MetaMapAdapter extends XmlAdapter<AdaptedMap, Map<String, String>> {
    public MapAdapter() {}

    @Override public AdaptedMap marshal(final Map<String, String> map) throws Exception {
        if (map == null) { return null; }

        final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        final DocumentBuilder db = dbf.newDocumentBuilder();
        final Document document = db.newDocument();
        final Element rootElement = document.createElement(getTagName());
        document.appendChild(rootElement);

        for (final Entry<String, String> entry : map.entrySet()) {
            final Element mapElement = document.createElement(entry.getKey());
            mapElement.setTextContent(entry.getValue());
            rootElement.appendChild(mapElement);
        }

        final AdaptedMap adaptedMap = new AdaptedMap();
        adaptedMap.setValue(document);

        return adaptedMap;
    }

    @Override public Map<String, String> unmarshal(final AdaptedMap adaptedMap) {
        if (adaptedMap == null) { return null; }

        final Map<String, String> map = new HashMap<String, String>();
        final Element rootElement = (Element) adaptedMap.getValue();
        final NodeList childNodes = rootElement.getChildNodes();

        for (int x = 0, size = childNodes.getLength(); x < size; x++) {
            final Node childNode = childNodes.item(x);

            if (childNode.getNodeType() == Node.ELEMENT_NODE) {
                map.put(childNode.getLocalName(), childNode.getTextContent());
            }
        }

        return map;
    }
}

By using Eclipselink MOXy, I'm able to get this JSON in return with the help of XmlPath:

{
  "meta": {
    "akey":"avalue",
    "bkey":"bvalue"
  }
}

Unfortunately, I'm unable to unmarshal to MyObject in reverse due to the usage of XmlPath to collapse the outer meta element.

On a side note, I'm also not able to use the new XmlVariableNode in Eclipselink 2.6 as I'm only allowed to use stable releases of the API :(

Anyone knows how I can resolve this?

Community
  • 1
  • 1
Staelen
  • 7,691
  • 5
  • 34
  • 30
  • Hi, Thanks for this. I followed the similar approach in my application but running to the issue and unable to get the desired output. If possible can you please have a look at this question where I have explained in-detail what issue I am facing with code sample. If you have some suggestion or workaround it would be really helpful for me: https://stackoverflow.com/questions/67648941/jaxb-moxy-unmarshalling-assigns-all-field-values-to-mapstring-object-rather-th – BATMAN_2008 May 23 '21 at 07:04

1 Answers1

3

On a side note, I'm also not able to use the new XmlVariableNode in Eclipselink 2.6 as I'm only allowed to use stable releases of the API :(

@XmlVariableNode has also been included in EclipseLink 2.5.1 which is now released:

This annotation is well suited for mapping your use case:

bdoughan
  • 147,609
  • 23
  • 300
  • 400
  • Hi, Thanks for this. I followed the similar approach in my application but running to the issue and unable to get the desired output. If possible can you please have a look at this question where I have explained in-detail what issue I am facing with code sample. If you have some suggestion or workaround it would be really helpful for me: https://stackoverflow.com/questions/67648941/jaxb-moxy-unmarshalling-assigns-all-field-values-to-mapstring-object-rather-th – BATMAN_2008 May 23 '21 at 07:04