Create Marshaller for JSON from unknown JAXBContex

2019-05-09 16:11发布

I have to use a lib that only gives me a JAXBContext to marshall and unmarshall XML data to Java objects. Also I don't ever see XML: Only the JAXB objects are passed to me. What I now need is a conversion of those objects not to XML, but to JSON.

Is there a way to create a marshaller from the given JAXBContext that can be used to generate JSON output?

The situation is that I'm not only transforming data. I also have logic that acts on the Java objects between XML and JSON (and manipulates the data). Also it's a two-way transformation. The JAXBContext is the information I have about the transformation between XML and Java objects - My intention was to reuse this context information for not having to implement a second transformation with a second technology different to JAXB. The JAXBContext (and its Java objects) already have the information about the XML structure; The automated recognition of that structure by JAXB is the time-saving reason for using it.

1条回答
The star\"
2楼-- · 2019-05-09 16:39

If your JAXB classes just use the basic annotations, you can take a look at JacksonJAXBAnnotations, allows Jackson mapper to recognize JAXN annotations. Four lines of code (in the simplest marshalling case) would be all you would need.

ObjectMapper mapper = new ObjectMapper();
JaxbAnnotationModule module = new JaxbAnnotationModule();
mapper.registerModule(module);
mapper.writeValue(System.out, yourJaxbObject);

You can see the link above for all the supported annotations. The maven artifact you'll need is

<dependency>
    <groupId>com.fasterxml.jackson.module</groupId>
    <artifactId>jackson-module-jaxb-annotations</artifactId>
    <version>2.4.0</version>
</dependency>
  • See the github for jackson-module-jaxb-annotations - Note this artifact has dependencies on jackson-core and jackson-databind. So if you're not using maven, then you will need to make sure to download these artifacts also

Simple Exmaple:

JAXB Class

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "hello",
    "world"
})
@XmlRootElement(name = "root")
public class Root {

    @XmlElement(required = true)
    protected String hello;
    @XmlElement(required = true)
    protected String world;

    // Getters and Setters
}

XML

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <hello>JAXB</hello>
    <world>Jackson</world>
</root>

Test

public class TestJaxbJackson {
    public static void main(String[] args) throws Exception {
        JAXBContext context = JAXBContext.newInstance(Root.class);
        Unmarshaller unmarshaller = context.createUnmarshaller();
        InputStream is = TestJaxbJackson.class.getResourceAsStream("test.xml");
        Root root = (Root)unmarshaller.unmarshal(is);
        System.out.println(root.getHello() + " " + root.getWorld());

        ObjectMapper mapper = new ObjectMapper();
        JaxbAnnotationModule module = new JaxbAnnotationModule();
        mapper.registerModule(module);
        mapper.writeValue(System.out, root);
    }
}

Result

{"hello":"JAXB","world":"Jackson"}

Update

Also see this post. It looks like MOXy also offers this support.

查看更多
登录 后发表回答