views:

1341

answers:

2

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;
    }
}
+1  A: 

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 ........
    }
Arnaudweb
Ok, i just figured your case was more complex than i though...
Arnaudweb
A: 

Check out the "Improving the Application" section of this page:

http://blogs.sun.com/enterprisetechtips/entry/configuring_json_for_restful_web

anon