如何使用 Jersey 将嵌套列表编组为 JSON?我得到一个空数组或一个包含数组的单元素字典数组
Posted
技术标签:
【中文标题】如何使用 Jersey 将嵌套列表编组为 JSON?我得到一个空数组或一个包含数组的单元素字典数组【英文标题】: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 【发布时间】:2010-11-11 20:12:15 【问题描述】:我正在开发一个使用 Jersey 将对象转换为 JSON 的项目。我希望能够写出嵌套列表,如下所示:
"data":[["one", "two", "three"], ["a", "b", "c"]]
我想首先将表示数据转换为 >> 的对象,我认为 Jersey 会做正确的事情。以上是作为空值列表输出的:
"data":[null, null]
在阅读了嵌套对象需要包装之后,我尝试了以下方法:
@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;
该代码输出以下内容,更接近我想要的内容:
"data":["data":["one", "two", "three"],"data":["a", "b", "c"]]
我希望第一个数据是列表列表,而不是单元素字典列表。我如何做到这一点?
这是我的 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】:你试过 jersey-json 吗??
将 jersey-json 添加到您的类路径(或您的 maven 依赖项)
然后使用这个:
@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;
您的资源中只需要这样的东西(假设 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】:查看此页面的“改进应用程序”部分:
http://blogs.oracle.com/enterprisetechtips/entry/configuring_json_for_restful_web
【讨论】:
【参考方案3】:我知道 qustion 相当陈旧,但我偶然发现了一个类似的问题,但我想渲染一个数组列表,即“List”,因为我从 jpa 获得的一个 db 和一个不使用实体的 nativ 查询的结果.
我就是这样解决的:
首先创建了一个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);
然后我创建了一个扩展 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);
然后我在 a 中使用它:
@GET
@Path("/id/search")
@Produces(JSON)
public ListWrapper search(@PathParam("id") Integer projectId )
return DatabaseManager.search(projectId);
搜索方法返回一个带有 Object[] 列表的 Listwrapper
希望这对某人有所帮助:-)
【讨论】:
以上是关于如何使用 Jersey 将嵌套列表编组为 JSON?我得到一个空数组或一个包含数组的单元素字典数组的主要内容,如果未能解决你的问题,请参考以下文章