Mat*_*all 26 java json jaxb jersey
我试图解组的单元素JSON数组:
[
{
"id":"42",
"status":"Active",
"name":"purple monkey dishwasher"
}
]
Run Code Online (Sandbox Code Playgroud)
相应的Java类(为简洁省略了getter和setter):
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Badge
{
@XmlElement(name="id")
private String id;
@XmlElement(name="status")
private Status status;
@XmlElement(name="name")
private String name;
public static enum Status
{
Active,
NotActive
}
}
Run Code Online (Sandbox Code Playgroud)
Jersey客户端代码发出HTTP请求并且应该将上述JSON解组为一个元素List<Foo>:
Client client = Client.create();
WebResource apiRoot = client.resource("http://localhost:9000/api");
List<Badge> badges = apiRoot.path("/badges").get(new GenericType<List<Badge>>(){});
Run Code Online (Sandbox Code Playgroud)
最后一行,特别是WebResource#get()调用,抛出以下异常:
javax.xml.bind.UnmarshalException: unexpected element (uri:"", local:"status"). Expected elements are <{}badge>
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext.handleEvent(UnmarshallingContext.java:662)
at com.sun.xml.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:258)
at com.sun.xml.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:253)
at com.sun.xml.bind.v2.runtime.unmarshaller.Loader.reportUnexpectedChildElement(Loader.java:120)
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext$DefaultRootLoader.childElement(UnmarshallingContext.java:1063)
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext._startElement(UnmarshallingContext.java:498)
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext.startElement(UnmarshallingContext.java:480)
at com.sun.xml.bind.v2.runtime.unmarshaller.InterningXmlVisitor.startElement(InterningXmlVisitor.java:75)
at com.sun.xml.bind.v2.runtime.unmarshaller.StAXStreamConnector.handleStartElement(StAXStreamConnector.java:247)
at com.sun.xml.bind.v2.runtime.unmarshaller.StAXStreamConnector.bridge(StAXStreamConnector.java:181)
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:369)
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:341)
at com.sun.jersey.core.provider.jaxb.AbstractListElementProvider.readFrom(AbstractListElementProvider.java:232)
at com.sun.jersey.api.client.ClientResponse.getEntity(ClientResponse.java:552)
at com.sun.jersey.api.client.ClientResponse.getEntity(ClientResponse.java:522)
at com.sun.jersey.api.client.WebResource.handle(WebResource.java:617)
at com.sun.jersey.api.client.WebResource.get(WebResource.java:191)
at com.redacted.badge.client.BadgerImpl.findAllBadges(BadgerImpl.java:105)
at com.redacted.webapp.admin.BadgeAction.unspecified(BadgeAction.java:40)
at org.apache.struts.actions.DispatchAction.dispatchMethod(DispatchAction.java:245)
at org.apache.struts.actions.DispatchAction.execute(DispatchAction.java:170)
at org.apache.struts.chain.commands.servlet.ExecuteAction.execute(ExecuteAction.java:58)
at org.apache.struts.chain.commands.AbstractExecuteAction.execute(AbstractExecuteAction.java:67)
at org.apache.struts.chain.commands.ActionCommandBase.execute(ActionCommandBase.java:51)
at org.apache.commons.chain.impl.ChainBase.execute(ChainBase.java:190)
at org.apache.commons.chain.generic.LookupCommand.execute(LookupCommand.java:304)
at org.apache.commons.chain.impl.ChainBase.execute(ChainBase.java:190)
at org.apache.struts.chain.ComposableRequestProcessor.process(ComposableRequestProcessor.java:283)
at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1913)
at org.apache.struts.action.ActionServlet.doGet(ActionServlet.java:449)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at com.opensymphony.module.sitemesh.filter.PageFilter.parsePage(PageFilter.java:119)
at com.opensymphony.module.sitemesh.filter.PageFilter.doFilter(PageFilter.java:55)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at com.redacted.webapp.filter.MemberFilter.doFilter(MemberFilter.java:83)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at com.redacted.webapp.filter.AuthFilter.doFilter(AuthFilter.java:113)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.displaytag.filter.ResponseOverrideFilter.doFilter(ResponseOverrideFilter.java:125)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at com.redacted.webapp.filter.LanguageHandlingFilter.doFilter(LanguageHandlingFilter.java:151)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at com.redacted.webapp.filter.SetCharacterEncodingFilter.doFilter(SetCharacterEncodingFilter.java:146)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at com.redacted.webapp.filter.PartnerFilter.doFilter(PartnerFilter.java:59)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at com.redacted.webapp.filter.SessionStatusFilter.doFilter(SessionStatusFilter.java:113)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:470)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at com.googlecode.psiprobe.Tomcat60AgentValve.invoke(Tomcat60AgentValve.java:30)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:859)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
at java.lang.Thread.run(Thread.java:680)
Run Code Online (Sandbox Code Playgroud)
我尝试了各种注释组合Badge,或使用数组而不是GenericType:
List<Badge> badges = Arrays.asList(apiRoot.path("/badges").get(Badge[].class));
Run Code Online (Sandbox Code Playgroud)
或使用中间体ClientResponse:
GenericType<List<Badge>> type = new GenericType<List<Badge>>(){};
ClientResponse clientResponse = apiRoot.path("/badges").get(ClientResponse.class);
List<Badge> badges = clientResponse.getEntity(type);
Run Code Online (Sandbox Code Playgroud)
但迄今为止都没有解决问题.
更令人困惑的是,我现有的设置在解组其他结构内部的JSON编码时没有问题Badge,如下所示:
{
"userid":"123456789",
"userbadges":[
{
"badge":{
"id":"42",
"status":"Active",
"name":"purple monkey dishwasher"
},
"earned":"2012-03-06 18:16:18.172"
}
]
}
Run Code Online (Sandbox Code Playgroud)
我究竟做错了什么?
Mat*_*all 23
通过使用Jersey Client实例JacksonJsonProvider的MessageBody(Reader|Writer)提供程序,我能够以最小的努力解决这个问题:
ClientConfig cfg = new DefaultClientConfig();
cfg.getClasses().add(JacksonJsonProvider.class);
Client client = Client.create(cfg);
Run Code Online (Sandbox Code Playgroud)
杰克逊的MessageBodyReader实施似乎比泽西JSON的表现更为出色.
感谢我如何自定义JAXB对象列表到JSON的序列化?指出我在杰克逊的方向.
bdo*_*han 14
注意: 我是EclipseLink JAXB(MOXy)的负责人,也是JAXB(JSR-222)专家组的成员.
您可以使用添加到EclipseLink 2.4中的MOXy组件的JSON Binding扩展来处理此用例:
演示
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());
}
}
}
Run Code Online (Sandbox Code Playgroud)
MOXyJSONProvider
下面是一个通用MessageBodyReader/ MessageBodyWriter可以与任何服务器/客户端一起使用以启用MOXy作为JSON绑定提供程序.
package forum9627170;
import java.io.*;
import java.lang.annotation.Annotation;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import javax.xml.transform.stream.StreamSource;
import javax.ws.rs.*;
import javax.ws.rs.core.*;
import javax.ws.rs.ext.*;
import javax.xml.bind.*;
@Provider
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class MOXyJSONProvider implements
MessageBodyReader<Object>, MessageBodyWriter<Object>{
@Context
protected Providers providers;
public boolean isReadable(Class<?> type, Type genericType,
Annotation[] annotations, MediaType mediaType) {
return true;
}
public Object readFrom(Class<Object> type, Type genericType,
Annotation[] annotations, MediaType mediaType,
MultivaluedMap<String, String> httpHeaders, InputStream entityStream)
throws IOException, WebApplicationException {
try {
Class domainClass = getDomainClass(genericType);
Unmarshaller u = getJAXBContext(domainClass, mediaType).createUnmarshaller();
u.setProperty("eclipselink.media-type", mediaType.toString());
u.setProperty("eclipselink.json.include-root", false);
return u.unmarshal(new StreamSource(entityStream), domainClass).getValue();
} catch(JAXBException jaxbException) {
throw new WebApplicationException(jaxbException);
}
}
public boolean isWriteable(Class<?> type, Type genericType,
Annotation[] annotations, MediaType mediaType) {
return true;
}
public void writeTo(Object object, Class<?> type, Type genericType,
Annotation[] annotations, MediaType mediaType,
MultivaluedMap<String, Object> httpHeaders,
OutputStream entityStream) throws IOException,
WebApplicationException {
try {
Marshaller m = getJAXBContext(getDomainClass(genericType), mediaType).createMarshaller();
m.setProperty("eclipselink.media-type", mediaType.toString());
m.setProperty("eclipselink.json.include-root", false);
m.marshal(object, entityStream);
} catch(JAXBException jaxbException) {
throw new WebApplicationException(jaxbException);
}
}
public long getSize(Object t, Class<?> type, Type genericType,
Annotation[] annotations, MediaType mediaType) {
return -1;
}
private JAXBContext getJAXBContext(Class<?> type, MediaType mediaType)
throws JAXBException {
ContextResolver<JAXBContext> resolver
= providers.getContextResolver(JAXBContext.class, mediaType);
JAXBContext jaxbContext;
if(null == resolver || null == (jaxbContext = resolver.getContext(type))) {
return JAXBContext.newInstance(type);
} else {
return jaxbContext;
}
}
private Class<?> getDomainClass(Type genericType) {
if(genericType instanceof Class) {
return (Class) genericType;
} else if(genericType instanceof ParameterizedType) {
return (Class) ((ParameterizedType) genericType).getActualTypeArguments()[0];
} else {
return null;
}
}
}
Run Code Online (Sandbox Code Playgroud)
欲获得更多信息
在GlassFish 4中,EclipseLink JAXB(MOXy)是Jersey使用的默认JSON绑定提供程序:
yve*_*lem 11
默认情况下,Jersey使用JAXB进行(un)编组过程,遗憾的是,JAXB JSON处理器不是标准处理器(忽略单元素数组,将空数组转换为单元素空数组......).
所以,你有两个选择:
使用Jackson客户端是通过以下方式完成的:
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>>() {});
Run Code Online (Sandbox Code Playgroud)
我有类似的问题,并通过以下解决
像这样制作一个JAXB上下文解析器
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;
}
}
Run Code Online (Sandbox Code Playgroud)为您的客户添加了上下文解析器
ClientConfig config = new DefaultClientConfig();
config.getClasses().add(JAXBContextResolver.class);
Client client = Client.create(config);
Run Code Online (Sandbox Code Playgroud)现在您可以获取对象数组
WebResource apiRoot = client.resource("http://localhost:9000/api");
Badge[] badges = apiRoot.path("/badges").get(Badge[].class);
Run Code Online (Sandbox Code Playgroud)如果你想要一个清单,只需使用
Arrays.asList(badges)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
44291 次 |
| 最近记录: |