我正在使用Jersey / Java创建一个REST服务器,我发现了一个奇怪的行为。
我在服务器上有一个方法,它返回一个对象数组作为Json
@GET
@Path("/files")
@Produces(MediaType.APPLICATION_JSON)
public Object getFiles() throws Exception{
DatabaseManager db = new DatabaseManager();
FileInfo[] result = db.getFiles();
return result;
}
代码正确执行,数据返回给客户端(jQuery ajax调用)。 问题是如果“result”数组有一个元素或多个元素,则返回数据的格式会发生变化。
一个元素的回应:
{"fileInfo":{"fileName":"weather.arff","id":"10"}}
有两个要素的回应:
{"fileInfo":[{"fileName":"weather.arff","id":"10"},{"fileName":"supermarket.arff","id":"11"}]}
如您所见,在第一个场景中,返回对象的“fileInfo”属性的值是一个对象,在第二种情况下,值是一个数组。 我究竟做错了什么?第一种情况不应该返回这样的东西:
{"fileInfo":[{"fileName":"weather.arff","id":"10"}]}
即。一个内部有一个对象的数组?
我知道我可以在客户端检测到这一点,但这似乎是一个非常难看的黑客。
感谢您的时间。
答案 0 :(得分:12)
我最终使用了杰克逊,也在泽西官方文档(http://jersey.java.net/nonav/documentation/latest/user-guide.html#json.pojo.approach.section)中有所描述。
之前我曾尝试过,但它没有用,因为我的项目的构建路径中没有jackson jar(根据文档,我认为它是内置于jersey的核心库中)。
我刚刚添加了jackson-all.jar文件(http://wiki.fasterxml.com/JacksonDownload)并在配置中启用了POJO支持
<init-param>
<param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
<param-value>true</param-value>
</init-param>
瞧!
答案 1 :(得分:5)
如果您使用JAXB构建JSON结果,则可以配置Jersey JSON处理器以获得更重要的JSON格式。
jersey official document有详细的配置:
要实现更重要的JSON格式更改,您需要配置Jersey JSON处理器本身。可以在JSONConfiguration实例上设置各种配置选项。然后可以进一步使用该实例来创建JSONConfigurated JSONJAXBContext,它充当该区域中的主要配置点。要将专门的JSONJAXBContext传递给Jersey,您最终需要实现一个JAXBContext ContextResolver:
@Provider
public class JAXBContextResolver implements ContextResolver<JAXBContext> {
private final JAXBContext context;
private final Set<Class> types;
private Class[] ctypes = { FileInfo.class}; //your pojo class
public JAXBContextResolver() throws Exception {
this.types = new HashSet(Arrays.asList(ctypes));
this.context = new JSONJAXBContext(JSONConfiguration.natural().build(),
ctypes); //json configuration
}
@Override
public JAXBContext getContext(Class<?> objectType) {
return (types.contains(objectType)) ? context : null;
}
}
答案 2 :(得分:1)
另请看下面的答案,为我解决了这个问题:
How can I customize serialization of a list of JAXB objects to JSON?
答案 3 :(得分:0)
您可以使用Jettison(与Jersey一起使用)并使用JSONObject
和JSONArray
作为返回值准备您希望自己拥有的结构。
它们位于org.codehaus.jettison.json
的{{1}}个包中,它是jettison-1.3.2.jar
的传递依赖
答案 4 :(得分:0)
您也可以尝试Genson库http://code.google.com/p/genson/。它与球衣很好地融为一体,只需将jar放在你的类路径中,一切都会顺利进行。它不需要你编写额外的代码,它应该像你现在拥有的那样工作,但没有任何奇怪的结果。
答案 5 :(得分:0)
I'm using cxf, here is my applicationContext.xml to force array in JSON,
<jaxrs:server id="myService" serviceName="MyService"
address="/mysvc">
<jaxrs:serviceBeans>
<ref bean="myServiceImpl"/>
</jaxrs:serviceBeans>
<jaxrs:providers>
<bean class="org.apache.cxf.jaxrs.provider.json.JSONProvider">
<property name="dropRootElement" value="true" />
<property name="supportUnwrapped" value="true" />
<property name="namespaceMap">
<map>
<entry key="http://example.com/myservice" value=""/>
</map>
</property>
<property name="arrayKeys">
<list>
<value>fileInfo</value>
</list>
</property>
</bean>
</jaxrs:providers>
</jaxrs:server>
答案 6 :(得分:0)
我已经挣扎了很多,找到了这个简单的解决方案
在你的pom.xml中:
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-jaxrs</artifactId>
<version>1.9.13</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-xc</artifactId>
<version>1.9.13</version>
</dependency>
在你的web.xml中:
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>com.other-packages;org.codehaus.jackson.jaxrs</param-value>
</init-param>
答案 7 :(得分:0)
将数组转换为ArrayList即可满足此处的要求。 我曾经遇到过类似的矛盾问题,在单个元素的情况下,我不得不返回Json Array Object而不是list。
我在下面的注释的帮助下完成了工作-
@JsonFormat(带有= JsonFormat.Feature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED)。 以下是JSON Pojo类的示例:
import java.util.List;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
@JsonIgnoreProperties(ignoreUnknown = true)
public class TAResponseMapper {
@JsonProperty("Response")
@JsonFormat(with = JsonFormat.Feature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED)
private List<TAResponse> responses;
public List<TAResponse> getResponses() {
return responses;
}
public void setResponses(List<TAResponse> responses) {
this.responses = responses;
}
}