Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.
You could leverage the JSON-Binding and external mapping document in EclipseLink JAXB (MOXy) to support your use case.
External Mapping File (oxml.xml)
You can use the @XmlPath(".")
extension in MOXy to flatten parts of your object model. Specify a path of "."
tells MOXy to include the referenced object in the parent node.
<?xml version="1.0"?>
<xml-bindings
xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
package-name="forum10699038">
<java-types>
<java-type name="Metadata">
<java-attributes>
<xml-element java-attribute="artistList" xml-path="."/>
</java-attributes>
</java-type>
<java-type name="Artist">
<java-attributes>
<xml-element java-attribute="ipiList" xml-path="."/>
</java-attributes>
</java-type>
</java-types>
</xml-bindings>
jaxb.properties
To specify MOXy as your JAXB provider you need to add a file called jaxb.properties
in the same package as your domain model with the following entry.
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
Demo
The code below populates the object model from your XML document, and then marshalled to JSON. It demonstrates how to leverage the external mapping file and put MOXy in JSON mode.
package forum10699038;
import java.io.File;
import java.util.*;
import javax.xml.bind.*;
import org.eclipse.persistence.jaxb.JAXBContextProperties;
public class Demo {
public static void main(String[] args) throws Exception {
// READ FROM XML
JAXBContext jcXML = JAXBContext.newInstance(Metadata.class);
File xml = new File("src/forum10699038/input.xml");
Unmarshaller unmarshaller = jcXML.createUnmarshaller();
Metadata metadata = (Metadata) unmarshaller.unmarshal(xml);
// WRITE TO JSON
Map<String, Object> properties = new HashMap<String, Object>(3);
properties.put(JAXBContextProperties.OXM_METADATA_SOURCE, "forum10699038/oxm.xml");
properties.put(JAXBContextProperties.MEDIA_TYPE, "application/json");
properties.put(JAXBContextProperties.JSON_INCLUDE_ROOT, false);
JAXBContext jcJSON = JAXBContext.newInstance(new Class[] {Metadata.class}, properties);
Marshaller marshaller = jcJSON.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(metadata, System.out);
}
}
Output
{
"artist" : [ {
"id" : "4302e264-1cf0-4d1f-aca7-2a6f89e34b36",
"type" : "Group",
"score" : "100",
"name" : "Farming Incident",
"ipi" : [ "1001" ]
} ]
}
MOXy and Jersey
You can easily use MOXy as your JSON provider in a JAXB-RS environment such as Jersey:
OTHER FILES
Below are versions of your files I created to make sure everything worked properly.
input.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<metadata xmlns="http://musicbrainz.org/ns/mmd-2.0#" xmlns:ext="http://musicbrainz.org/ns/ext#-2.0">
<artist-list offset="0" count="1">
<artist ext:score="100" type="Group"
id="4302e264-1cf0-4d1f-aca7-2a6f89e34b36">
<name>Farming Incident</name>
<ipi-list>
<ipi>1001</ipi>
</ipi-list>
</artist>
</artist-list>
</metadata>
Metadata
package forum10699038;
import javax.xml.bind.annotation.*;
@XmlRootElement
public class Metadata {
@XmlElement(name="artist-list")
ArtistList artistList;
}
ArtistList
package forum10699038;
import java.util.List;
public class ArtistList {
private List<Artist> artist;
}
Artist
package forum10699038;
import javax.xml.bind.annotation.*;
@XmlType(propOrder={"name", "ipiList"})
public class Artist {
@XmlAttribute
private String id;
@XmlAttribute
private String type;
@XmlAttribute(namespace="http://musicbrainz.org/ns/ext#-2.0")
private String score;
@XmlElement(name="ipi-list")
private IPIList ipiList;
private String name;
}
IPList
package forum10699038;
import java.util.List;
public class IPIList {
private List<String> ipi;
}
package-info
@XmlSchema(
namespace = "http://musicbrainz.org/ns/mmd-2.0#",
elementFormDefault = XmlNsForm.QUALIFIED,
xmlns={
@XmlNs(prefix="", namespaceURI = "http://musicbrainz.org/ns/mmd-2.0#")
}
)
@XmlAccessorType(XmlAccessType.FIELD)
package forum10699038;
import javax.xml.bind.annotation.*;