如何使用Jersey将嵌套列表编组为JSON ?我得到一个空数组或包含数组的一个元素字典数组

时间:2022-03-17 11:10:57

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:

我正在做一个项目,用Jersey把对象转换成JSON。我希望能够写出嵌套列表,如下所示:

{"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:

我想要将第一个表示的数据转换为 >>,我认为Jersey会做正确的事情。上述输出为一列空值:

{"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:

这是我的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;
    }
}

3 个解决方案

#1


5  

Have you tried jersey-json ??

你试过jersey-json吗?

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

将jersey-json添加到类路径(或您的maven依赖项)

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)

在你的ressources中只需要这样的东西(假设DetailProduit是你想要序列化的对象,然后是DetailProduit。java被标记为jaxb,并且在package.of.your.model中)

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

#2


1  

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

查看本页的“改善申请”部分:

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

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

#3


0  

I know the qustion is rather old but I stumbled on a similar problem but I wanted to render a List of Arrays ie.´List´ due to a result from a db which I got from jpa and a nativ query without using Entities.

我知道qustion是相当古老的,但我偶然发现了一个类似的问题,但我想呈现一个数组ie列表。´列表´由于结果从db我从jpa和nativ查询不使用实体。

This is how I solved it:

我就是这样解决的:

First Created a ListWrapper.java:

首先创建了一个ListWrapper.java:

import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class ListWrapper extends ArrayList {

    @SuppressWarnings("unchecked")
    public ListWrapper() {
        super();
    }

    public ListWrapper(List list) {
        super(list);
    }
}

And then I created a class extending AbstractMessageReaderWriterProvider

然后我创建了一个扩展AbstractMessageReaderWriterProvider类的类。

import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONException;

import com.sun.jersey.core.provider.AbstractMessageReaderWriterProvider;

@Provider
@Produces("*/*")
@Consumes("*/*")
public class ListObjectArrayMessagereaderWriterProvider extends    AbstractMessageReaderWriterProvider<ListWrapper> {

    public boolean supports(Class type) {
        return type == ListWrapper.class;
    }

    @Override
    public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
        return type == ListWrapper.class;
    }

    @Override
    public ListWrapper readFrom(Class<ListWrapper> type, Type genericType, Annotation[] annotations, MediaType mediaType,
        MultivaluedMap<String, String> httpHeaders, InputStream entityStream) throws IOException, WebApplicationException {
        throw new IllegalArgumentException("Not implemented yet.");
    }

    @Override
    public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
        return type == ListWrapper.class;
    }

    @SuppressWarnings("unchecked")
    @Override
    public void writeTo(ListWrapper t, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType,
        MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream) throws IOException, WebApplicationException {

        final Iterator<Object[]> iterator = t.iterator();

        OutputStreamWriter writer = new OutputStreamWriter(entityStream, getCharset(mediaType));
        final JSONArray jsonArrayOuter = new JSONArray();
        while (iterator.hasNext()) {
            final Object[] objs = iterator.next();
            JSONArray jsonArrayInner = new JSONArray(Arrays.asList(objs));
            jsonArrayOuter.put(jsonArrayInner);
        }
        try {
            jsonArrayOuter.write(writer);
            writer.write("\n");
            writer.flush();
        } catch (JSONException je) {
            throw new WebApplicationException(new Exception(ImplMessages.ERROR_WRITING_JSON_ARRAY(), je), 500);
        }
    }
}

Then I using it in a as this:

然后我用a表示

    @GET
    @Path("/{id}/search")
    @Produces(JSON)
    public ListWrapper search(@PathParam("id") Integer projectId ) {
        return DatabaseManager.search(projectId);
    }

The search method is returning a Listwrapper with a list of Object[]

搜索方法返回一个Listwrapper,其中包含一个对象列表[]

Hope this helps someone :-)

希望这能帮助某人:

#1


5  

Have you tried jersey-json ??

你试过jersey-json吗?

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

将jersey-json添加到类路径(或您的maven依赖项)

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)

在你的ressources中只需要这样的东西(假设DetailProduit是你想要序列化的对象,然后是DetailProduit。java被标记为jaxb,并且在package.of.your.model中)

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

#2


1  

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

查看本页的“改善申请”部分:

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

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

#3


0  

I know the qustion is rather old but I stumbled on a similar problem but I wanted to render a List of Arrays ie.´List´ due to a result from a db which I got from jpa and a nativ query without using Entities.

我知道qustion是相当古老的,但我偶然发现了一个类似的问题,但我想呈现一个数组ie列表。´列表´由于结果从db我从jpa和nativ查询不使用实体。

This is how I solved it:

我就是这样解决的:

First Created a ListWrapper.java:

首先创建了一个ListWrapper.java:

import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class ListWrapper extends ArrayList {

    @SuppressWarnings("unchecked")
    public ListWrapper() {
        super();
    }

    public ListWrapper(List list) {
        super(list);
    }
}

And then I created a class extending AbstractMessageReaderWriterProvider

然后我创建了一个扩展AbstractMessageReaderWriterProvider类的类。

import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONException;

import com.sun.jersey.core.provider.AbstractMessageReaderWriterProvider;

@Provider
@Produces("*/*")
@Consumes("*/*")
public class ListObjectArrayMessagereaderWriterProvider extends    AbstractMessageReaderWriterProvider<ListWrapper> {

    public boolean supports(Class type) {
        return type == ListWrapper.class;
    }

    @Override
    public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
        return type == ListWrapper.class;
    }

    @Override
    public ListWrapper readFrom(Class<ListWrapper> type, Type genericType, Annotation[] annotations, MediaType mediaType,
        MultivaluedMap<String, String> httpHeaders, InputStream entityStream) throws IOException, WebApplicationException {
        throw new IllegalArgumentException("Not implemented yet.");
    }

    @Override
    public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
        return type == ListWrapper.class;
    }

    @SuppressWarnings("unchecked")
    @Override
    public void writeTo(ListWrapper t, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType,
        MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream) throws IOException, WebApplicationException {

        final Iterator<Object[]> iterator = t.iterator();

        OutputStreamWriter writer = new OutputStreamWriter(entityStream, getCharset(mediaType));
        final JSONArray jsonArrayOuter = new JSONArray();
        while (iterator.hasNext()) {
            final Object[] objs = iterator.next();
            JSONArray jsonArrayInner = new JSONArray(Arrays.asList(objs));
            jsonArrayOuter.put(jsonArrayInner);
        }
        try {
            jsonArrayOuter.write(writer);
            writer.write("\n");
            writer.flush();
        } catch (JSONException je) {
            throw new WebApplicationException(new Exception(ImplMessages.ERROR_WRITING_JSON_ARRAY(), je), 500);
        }
    }
}

Then I using it in a as this:

然后我用a表示

    @GET
    @Path("/{id}/search")
    @Produces(JSON)
    public ListWrapper search(@PathParam("id") Integer projectId ) {
        return DatabaseManager.search(projectId);
    }

The search method is returning a Listwrapper with a list of Object[]

搜索方法返回一个Listwrapper,其中包含一个对象列表[]

Hope this helps someone :-)

希望这能帮助某人: