How do I marshal nested lists as JSON using Jersey? I get an array of nulls or an array of one-element dictionaries containing an array

arrays, java, jaxb, jersey, json

Solution

Have you tried jersey-json ??

Add jersey-json to your classpath (or your maven dependencies)

Then use this :

@Provider
public class JAXBContextResolver implements ContextResolver<JAXBContext> {

    private final JAXBContext context;

    public JAXBContextResolver() throws Exception {
        this.context = new JSONJAXBContext(JSONConfiguration.natural().build(), "package.of.your.model");
    }

    public JAXBContext getContext(Class<?> objectType) {
        return context;
    }

}

You only need something like this in your ressources (supposing DetailProduit is your object you want to serialize and that DetailProduit.java is jaxb tagged and in package.of.your.model)

@GET
@Produces(MediaType.APPLICATION_JSON)
@Path("/{code}")
public DetailProduit getDetailProduit(@PathParam("code") String code) {
        .... Your Code ........
    }

Problem

I'm working on a project which uses Jersey to convert objects to JSON. I'd like to be able to write out nested lists, like so: ``` {"data":[["one", "two", "three"], ["a", "b", "c"]]} ``` The object I'd like to convert first represented data as a <LinkedList<LinkedList<String>>>, and I figured Jersey would just do the right thing. The above was output as a list of nulls: ``` {"data":[null, null]} ``` After reading that nested objects need to be wrapped, I tried the following: ``` @XmlRootElement(name = "foo") @XmlType(propOrder = {"data"}) public class Foo { private Collection<FooData> data = new LinkedList<FooData>(); @XmlElement(name = "data") public Collection<FooData> getData() { return data; } public void addData(Collection data) { FooData d = new FooData(); for(Object o: data) { d.getData().add(o == null ? (String)o : o.toString()); } this.data.add(d); } @XmlRootElement(name = "FooData") public static class FooData { private Collection<String> data = new LinkedList<String>(); @XmlElement public Collection<String> getData() { return data; } } } ``` That code outputs what's below, which is closer to what I want: ``` {"data":[{"data":["one", "two", "three"]},{"data":["a", "b", "c"]}]} ``` I want the first data to be a list of lists, not a list of one-element dictionaries. How do I achieve this? Here's my JAXBContentResolver: ``` @Provider public class JAXBContextResolver implements ContextResolver<JAXBContext> { private JAXBContext context; private Set<Class<?>> types; // Only parent classes are required here. Nested classes are implicit. protected Class<?>[] classTypes = new Class[] {Foo.class}; protected Set<String> jsonArray = new HashSet<String>(1) { { add("data"); } }; public JAXBContextResolver() throws Exception { Map<String, Object> props = new HashMap<String, Object>(); props.put(JSONJAXBContext.JSON_NOTATION, JSONJAXBContext.JSONNotation.MAPPED); props.put(JSONJAXBContext.JSON_ROOT_UNWRAPPING, Boolean.TRUE); props.put(JSONJAXBContext.JSON_ARRAYS, jsonArray); this.types = new HashSet<Class<?>>(Arrays.asList(classTypes)); this.context = new JSONJAXBContext(classTyes, props); } public JAXBContext getContext(Class<?> objectType) { return (types.contains(objectType)) ? context : null; } } ```

Original source