JAXB / Jackson handling arrays
I'm currently writing a Jersey REST interface for a web application. What I want is the ability to be able to serialize a JSON and XML request to the same object however I'm having trouble getting the Jersey (i.e. JAXB / Jackson) to consume the XML and JSON in the format I want.
The XML structure looks like so:
<?xml version="1.0" encoding="UTF-8" ?>
<message>
<buckets>
<bucket>
<channels>
<channel>T开发者_开发知识库est A</channel>
<channel>Test B</channel>
</channels>
<text>This is sample text</text>
</bucket>
<bucket>
<channels>
....
</channels>
<text>This is sample text</text>
</bucket>
</buckets>
<userId>10</userId>
</message>
The class looks like:
@XmlRootElement(name="message")
public class MultiMessageRS {
public static class Bucket {
private List<String> channels;
private String text;
public Bucket () {}
@XmlElementWrapper(name="channels")
@XmlElement(name="channel")
public List<String> getChannels() {
return channels;
}
public void setChannels(List<String> channels) {
this.channels = channels;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
}
private List<Bucket> buckets;
private long userId;
public MultiMessageRS () {}
@XmlElementWrapper(name="buckets")
@XmlElement(name="bucket")
public List<Bucket> getBuckets() {
return buckets;
}
public void setBuckets(List<Bucket> buckets) {
this.buckets = buckets;
}
public long getUserId() {
return userId;
}
public void setUserId(long userId) {
this.userId = userId;
}
}
This works fine for the XML however it's unable to consume the JSON in the format I would like. Namely, the issue is that it isn't picking up the channels array. The format is as follows:
{
"buckets":[
{
"bucket":{
"channels":[
"twitter",
"mobile"
],
"text":"This is sample text"
},
"bucket":{
"channels":[
"email",
"voice"
],
"text":"This is sample text"
}
}
],
"userId":"10"
}
From it to work correctly with the JSON, I would have to do something like adding a 'channel' array under 'channels' which is pretty dodgy. How will I be able to handle this situation?
Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB 2 (JSR-222) expert group.
EclipseLink JAXB (MOXy) offers native support for JSON-binding. Below is an example demonstrating the XML and JSON representation of the model you posted in your question.
Demo
package forum7735245;
import java.io.File;
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(MultiMessageRS.class);
File xml = new File("src/forum7735245/input.xml");
Unmarshaller unmarshaller = jc.createUnmarshaller();
MultiMessageRS message = (MultiMessageRS) unmarshaller.unmarshal(xml);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.setProperty("eclipselink.media-type", "application/json");
marshaller.setProperty("eclipselink.json.include-root", false);
marshaller.marshal(message, System.out);
}
}
input.xml
<?xml version="1.0" encoding="UTF-8" ?>
<message>
<buckets>
<bucket>
<channels>
<channel>Test A</channel>
<channel>Test B</channel>
</channels>
<text>This is sample text</text>
</bucket>
<bucket>
<channels>
....
</channels>
<text>This is sample text</text>
</bucket>
</buckets>
<userId>10</userId>
</message>
Output
{
"buckets" : {
"bucket" : [ {
"channels" : {
"channel" : [ "Test A", "Test B" ]
},
"text" : "This is sample text"
}, {
"channels" : {},
"text" : "This is sample text"
} ]
},
"userId" : 10
}
For More Information
- JSON Binding with EclipseLink MOXy - Twitter Example
- MOXy as Your JAX-RS JSON Provider - Server Side
I think you are overcomplicating your JSON (as well as making it invalid by repeating same property name). It seems like what you might want to use is something like:
{
"buckets":[
{
"channels":[
"twitter",
"mobile"
],
"text":"This is sample text"
}, {
"channels":[
"email",
"voice"
],
"text":"This is sample text"
}
],
"userId":"10"
}
which should work as expected.
精彩评论