Search code examples
jsonrestjaxbmarshallingmoxy

How to marshall a Java class to JSON with JAXB, JAX-RS 2.0 and MOXy


I have a web application Running on Tomcat 7 that used Jersey 1.8 to provide a REST service producing a JSON file based on the class file shown below.

@XmlRootElement
public class Person {

    public String firstname;
    public String lastname;
    public String email;

    public Person() {
    }

    public Person(String firstname, String lastname, String email) {
        this.firstname = firstname;
        this.lastname = lastname;
        this.email = email;
   }
}

I use the service shown below to produce a JSON file.

@GET
@Path("allpersons")
@Produces(MediaType.APPLICATION_JSON)
public Collection<Person> getAllPersons() {
    Person p1 = new Person("Albert","Marks","[email protected]");
    Person p2 = new Person("David","Spencer","[email protected]");
    Collection<Person> all = new ArrayList<>();
    all.add(p1);
    all.add(p2);
    return all;
}

This would lead to a JSON file with the following form:

{ "person": [  
    { "firstname":"Albert",
      "lastname":"Marks",
      "email":"[email protected]"},
    {  "firstname":"David",
       "lastname":"Spencer",
       "[email protected]"} 
  ]
}

This all worked just fine but then I had to update to Jersey 2.10. Since them I also use jersey-media-moxy 2.10. However, the resulting JSON now is as follows which breaks JavaScript libraries calling the service:

[  
    { "firstname":"Albert",
      "lastname":"Marks",
      "email":"[email protected]"},
    {  "firstname":"David",
       "lastname":"Spencer",
       "[email protected]"} 
]

I compared the XML files produced using both versions of Jersey and they are absolutely identical. Hence I guess it must be some configuration issue with MOXy. I tried providing an own class inheriting javax.ws.rs.core.Application but the effect is still the same. Any idea what the cause is?


Solution

  • MOXy's JSON-binding renders a Java java.util.Collection as a JSON array (make's sense right?). If you want it to include the root level person key then instead of returning Collection<Person> you could return an instance of a class that had a Collection property called person or annotated with @XmlElement(name="person").