Java 无法使用Jersey客户端解组对象的JSON数组
我正在尝试解组的一个单元素JSON数组:Java 无法使用Jersey客户端解组对象的JSON数组,java,json,jaxb,jersey,Java,Json,Jaxb,Jersey,我正在尝试解组的一个单元素JSON数组: [ { "id":"42", "status":"Active", "name":"purple monkey dishwasher" } ] 相应的Java类(为简洁起见省略了getter和setter): Jersey客户端代码,它发出HTTP请求,并应将上述JSON解组为一个元素列表: 我在Badge上尝试了多种注释组合,或者使用数组代替GenericType: List<Badge>
[
{
"id":"42",
"status":"Active",
"name":"purple monkey dishwasher"
}
]
相应的Java类(为简洁起见省略了getter和setter):
Jersey客户端代码,它发出HTTP请求,并应将上述JSON解组为一个元素列表
:
我在Badge
上尝试了多种注释组合,或者使用数组代替GenericType
:
List<Badge> badges = Arrays.asList(apiRoot.path("/badges").get(Badge[].class));
但到目前为止,还没有人解决这个问题
更令人困惑的是,我现有的设置在解开JSON编码的Badge
s(位于其他结构内部)时没有问题,如下所示:
{
"userid":"123456789",
"userbadges":[
{
"badge":{
"id":"42",
"status":"Active",
"name":"purple monkey dishwasher"
},
"earned":"2012-03-06 18:16:18.172"
}
]
}
我做错了什么?这可能与制作人没有将单例列表正确编码为JSON有关。有关更全面的解释和建议的解决方案,请参阅 根据本文所描述的内容,并根据错误消息,我猜测将生成以下内容:
{
{
"id":"42",
"status":"Active",
"name":"purple monkey dishwasher"
}
}
根据这篇文章,解决方案在于扩展和定制提供者,以更正单例列表和空列表如何格式化为JSON
不幸的是,这篇文章是用德语写的,我必须自己翻译——如果它不能真正解决你的问题,请告诉我。如果是这样的话,这篇文章的作者德克·迪特马尔(Dirk Dittmar)就功不可没
PS-如果你像我一样使用Chrome来翻译页面,请确保切换回原始页面,以查看代码片段,因为其中的一部分被错误地“翻译”为空白。注意:我是专家组的负责人和成员 您可以使用添加到EclipseLink 2.4中MOXy组件的JSON绑定扩展来处理此用例: 演示 Jersey客户端API允许您从客户端的服务器端利用相同的
MessageBodyReader
/MessageBodyWriter
package forum9627170;
import java.util.List;
import org.example.Customer;
import com.sun.jersey.api.client.*;
import com.sun.jersey.api.client.config.*;
public class Demo {
public static void main(String[] args) {
ClientConfig cc = new DefaultClientConfig();
cc.getClasses().add(MOXyJSONProvider.class);
Client client = Client.create(cc);
WebResource apiRoot = client.resource("http://localhost:9000/api");
List<Badge> badges = apiRoot.path("/badges").accept("application/json").get(new GenericType<List<Badge>>(){});
for(Badge badge : badges) {
System.out.println(badge.getId());
}
}
}
了解更多信息
更新 在GlassFish 4中,EclipseLink JAXB(MOXy)是Jersey使用的默认JSON绑定提供程序:
MessageBody(Reader | Writer)
提供者,以最小的努力解决这个问题:
ClientConfig cfg = new DefaultClientConfig();
cfg.getClasses().add(JacksonJsonProvider.class);
Client client = Client.create(cfg);
Jackson的MessageBodyReader
实现似乎比Jersey JSON实现表现得更好
感谢您为我指明了Jackson的方向。默认情况下,Jersey使用JAXB进行(un)编组过程,不幸的是,JAXB JSON处理器不是标准的(忽略单元素数组,将空数组转换为单元素空数组…) 因此,您有两个选择:
ClientConfig clientConfig = new DefaultClientConfig();
clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
Client client = Client.create(clientConfig);
List<Badge> badges = client.resource("/badges").getEntity(new GenericType<List<Badge>>() {});
ClientConfig ClientConfig=newdefaultclientconfig();
clientConfig.getFeatures().put(JSONConfiguration.FEATURE\u POJO\u映射,Boolean.TRUE);
Client=Client.create(clientConfig);
List badges=client.resource(“/badges”).getEntity(新的GenericType(){});
我有一个类似的问题,并通过以下方法得到解决
import java.util.ArrayList;
import java.util.List;
import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;
import javax.xml.bind.JAXBContext;
import com.sun.jersey.api.json.JSONConfiguration;
import com.sun.jersey.api.json.JSONJAXBContext;
@Provider
public class JAXBContextResolver implements ContextResolver<JAXBContext> {
private JAXBContext context;
private Class<?>[] types = { Badge.class };
private List<Class<?>> classes = new ArrayList<Class<?>>();
public JAXBContextResolver() throws Exception {
this.context = new JSONJAXBContext(JSONConfiguration.natural().build(), types);
for (Class<?> clazz : types) {
classes.add(clazz);
}
}
public JAXBContext getContext(Class<?> objectType) {
return classes.contains(objectType) ? context : null;
}
}
WebResource apiRoot = client.resource("http://localhost:9000/api");
Badge[] badges = apiRoot.path("/badges").get(Badge[].class);
Arrays.asList(badges)
导入这个
泽西岛
泽西json
1.17
编译
这是破译密码
import com.sun.jersey.api.json.JSONJAXBContext;
import com.sun.jersey.api.json.JSONUnmarshaller;
public static <T> T unmarshalJson(String jsonTxt, Class<T> clazz) throws JAXBException {
JSONJAXBContext jctx = new JSONJAXBContext(clazz);
JSONUnmarshaller unm = jctx.createJSONUnmarshaller();
return (T)unm.unmarshalFromJSON(new StringReader(jsonTxt), clazz);
}
import com.sun.jersey.api.json.JSONJAXBContext;
导入com.sun.jersey.api.json.jsonumarshaller;
公共静态T unmarshalJson(字符串jsonTxt,类clazz)抛出JAXBEException{
JSONJAXBContext jctx=新的JSONJAXBContext(clazz);
jsonumarshaller unm=jctx.createjsonumarshaller();
返回(T)unm.unmarshalFromJSON(新的StringReader(jsonTxt),clazz);
}
谢谢,我来试一试。我很想知道为什么这不能开箱即用——你知道吗?另外,我知道在你发布答案之前只是时间问题。:)@MΓΓББLL-我已经更新了我的答案。我相信它不是开箱即用的,因为你的收藏中的物品没有徽章
作为根元素。哦,很有趣。再看一看JSON我能解组和JSON我不能解组之间的区别,我明白你的意思了。这种方法不是标准方法。要在Jersey中生成和使用标准JSON,必须使用Jackson!这很简单、快速,Jersey团队就是这样设计的。@yvesamsellem-(-1?)。这种方法使用标准的“MessageBodyReader/Writer”接口与Jersey客户端API交互,并清楚地表明您不需要使用Jackson在Jersey中生成和使用标准JSON。GlassFish()中已经有了MOXy的早期版本,而包含JSON绑定的版本将包含在未来的GlassFish版本中。堆栈跟踪清楚地表明JAXB实现与JSON一起使用,MOXy比Jackson支持更多的JAXB注释。是的,正如前面所说,我正在尝试Jackson,这似乎不那么奇怪。很高兴知道。仅当您希望自定义(取消)编组过程时,才需要使用自定义JacksonProvider。如果不这样做,使用Jersey提供的默认提供程序就足够了(JSONConfiguration功能)。事实上,我使用的是一个自定义提供程序,这样我就可以在Jackson注释旁边使用JAXB注释:默认Jersey Jackson提供程序配置为在Jackson注释旁边使用JAXB注释;-)唯一的问题是没有记录此提供程序的确切配置:-(我(基本上)只是使用JacksonJsonProvider
@mΓΓΓБLL,而不是繁琐地创建我自己的提供程序-听起来不错!感谢您的关注
ClientConfig clientConfig = new DefaultClientConfig();
clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
Client client = Client.create(clientConfig);
List<Badge> badges = client.resource("/badges").getEntity(new GenericType<List<Badge>>() {});
import java.util.ArrayList;
import java.util.List;
import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;
import javax.xml.bind.JAXBContext;
import com.sun.jersey.api.json.JSONConfiguration;
import com.sun.jersey.api.json.JSONJAXBContext;
@Provider
public class JAXBContextResolver implements ContextResolver<JAXBContext> {
private JAXBContext context;
private Class<?>[] types = { Badge.class };
private List<Class<?>> classes = new ArrayList<Class<?>>();
public JAXBContextResolver() throws Exception {
this.context = new JSONJAXBContext(JSONConfiguration.natural().build(), types);
for (Class<?> clazz : types) {
classes.add(clazz);
}
}
public JAXBContext getContext(Class<?> objectType) {
return classes.contains(objectType) ? context : null;
}
}
ClientConfig config = new DefaultClientConfig();
config.getClasses().add(JAXBContextResolver.class);
Client client = Client.create(config);
WebResource apiRoot = client.resource("http://localhost:9000/api");
Badge[] badges = apiRoot.path("/badges").get(Badge[].class);
Arrays.asList(badges)
import com.sun.jersey.api.json.JSONJAXBContext;
import com.sun.jersey.api.json.JSONUnmarshaller;
public static <T> T unmarshalJson(String jsonTxt, Class<T> clazz) throws JAXBException {
JSONJAXBContext jctx = new JSONJAXBContext(clazz);
JSONUnmarshaller unm = jctx.createJSONUnmarshaller();
return (T)unm.unmarshalFromJSON(new StringReader(jsonTxt), clazz);
}