从 JSON 字符串反序列化 ArrayList 时出现 Jersey 错误
Jersey error deserializing ArrayList from JSON string
这是重要信息。使用泽西岛 1.6。将相同类型的列表序列化到前端没有问题,并且不同类型的列表不会在应用程序的其他地方来回引起问题,所以我认为问题出在 bean 本身。我在没有附加路径参数的情况下尝试过这个,我遵循所有的 bean 约定,数据在 ajax 之前看起来很好......真的不知道我的问题在哪里。除了它是 NPE 之外,没有真正提供任何信息。
豆子
public class TheBean implements Serializable{
private static final long serialVersionUID = 1L;
private String beanId;
private String name;
private String beanType;
private Boolean group;
public TheBean(){}
public TheBean(String beanId, String name, String beanType, boolean isGroup) {
super();
this.beanId = beanId;
this.name = name;
this.beanType = beanType;
this.group = isGroup;
}
public String getBeanId() {
return beanId;
}
public void setBeanId(String beanId) {
this.beanId = beanId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getBeanType() {
return beanType;
}
public void setBeanType(String beanType) {
this.beanType = beanType;
}
public boolean isGroup() {
return group;
}
public void setGroup(boolean group) {
this.group = group;
}
}
网络服务
@POST
@Path("/update/{parentId}")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public Response updateTheBeanList(ArrayList<TheBean> routeList, @PathParam("parentId") String parentId){
//code
}
客户端代码
var beanListArray = beanListTable.fnGetData();//looks good here
var json = JSON.stringify(beanListArray);//and here
$.ajax({
dataType: 'text',
type: "POST",
data: json,
url: '${pageContext.request.contextPath}/rest/beanList/update/' + parentId, //looks good here
});
异常
java.lang.NullPointerException
at org.codehaus.jackson.xc.JaxbAnnotationIntrospector.findAdapter(JaxbAnnotationIntrospector.java:1058)
at org.codehaus.jackson.xc.JaxbAnnotationIntrospector.findDeserializer(JaxbAnnotationIntrospector.java:644)
at org.codehaus.jackson.xc.JaxbAnnotationIntrospector.findDeserializer(JaxbAnnotationIntrospector.java:74)
at org.codehaus.jackson.map.AnnotationIntrospector.findDeserializer(AnnotationIntrospector.java:634)
at org.codehaus.jackson.map.AnnotationIntrospector$Pair.findDeserializer(AnnotationIntrospector.java:1286)
有问题的依赖关系
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-bundle</artifactId>
<version>1.6</version>
</dependency>
<dependency>
<groupId>com.sun.jersey.contribs</groupId>
<artifactId>jersey-multipart</artifactId>
<version>1.6</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-server</artifactId>
<version>1.6</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.8.0</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-json</artifactId>
<version>1.6</version>
</dependency>
在你的情况下,Jackson 使用 class org.codehaus.jackson.xc.JaxbAnnotationIntrospector
到 deserialize/serialize ArrayList 和你的 POJO(我假设你在 web.xml 中配置了 com.sun.jersey.api.json.POJOMappingFeature
).
Jackson 正在寻找不存在的注释。请参阅 JaxbAnnotationIntrospector.java
中的第 643 行:
Class potentialAdaptee = ((Member)am.getAnnotated()).getDeclaringClass();
其中 am.getAnnotated()
是 null
。
因为您还没有 "annotated any of the beans with @XmlRootElement",一个简单的解决方案是禁用 JaxbAnnotationIntrospector
。这可以通过注册自定义 ContextResolver
提供自己的 ObjectMapper
实例来完成。
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.SerializationConfig.Feature;
import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;
@Provider
public class PojoObjectMapperProvider implements ContextResolver<ObjectMapper> {
final ObjectMapper defaultObjectMapper;
public PojoObjectMapperProvider() {
defaultObjectMapper = new ObjectMapper();
defaultObjectMapper.configure(Feature.INDENT_OUTPUT, true);
}
@Override
public ObjectMapper getContext(Class<?> type) {
return defaultObjectMapper;
}
}
要注册class:
import javax.ws.rs.core.Application;
import java.util.HashSet;
import java.util.Set;
public class MyApplication extends Application {
@Override
public Set<Class<?>> getClasses() {
final Set<Class<?>> classes = new HashSet<>();
classes.add(PojoObjectMapperProvider.class);
return classes;
}
}
如果你不使用 web.xml:
ApplicationAdapter rc = new ApplicationAdapter(new MyApplication());
rc.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
SelectorThread threadSelector = GrizzlyServerFactory.create(BASE_URI, rc);
这是重要信息。使用泽西岛 1.6。将相同类型的列表序列化到前端没有问题,并且不同类型的列表不会在应用程序的其他地方来回引起问题,所以我认为问题出在 bean 本身。我在没有附加路径参数的情况下尝试过这个,我遵循所有的 bean 约定,数据在 ajax 之前看起来很好......真的不知道我的问题在哪里。除了它是 NPE 之外,没有真正提供任何信息。
豆子
public class TheBean implements Serializable{
private static final long serialVersionUID = 1L;
private String beanId;
private String name;
private String beanType;
private Boolean group;
public TheBean(){}
public TheBean(String beanId, String name, String beanType, boolean isGroup) {
super();
this.beanId = beanId;
this.name = name;
this.beanType = beanType;
this.group = isGroup;
}
public String getBeanId() {
return beanId;
}
public void setBeanId(String beanId) {
this.beanId = beanId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getBeanType() {
return beanType;
}
public void setBeanType(String beanType) {
this.beanType = beanType;
}
public boolean isGroup() {
return group;
}
public void setGroup(boolean group) {
this.group = group;
}
}
网络服务
@POST
@Path("/update/{parentId}")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public Response updateTheBeanList(ArrayList<TheBean> routeList, @PathParam("parentId") String parentId){
//code
}
客户端代码
var beanListArray = beanListTable.fnGetData();//looks good here
var json = JSON.stringify(beanListArray);//and here
$.ajax({
dataType: 'text',
type: "POST",
data: json,
url: '${pageContext.request.contextPath}/rest/beanList/update/' + parentId, //looks good here
});
异常
java.lang.NullPointerException
at org.codehaus.jackson.xc.JaxbAnnotationIntrospector.findAdapter(JaxbAnnotationIntrospector.java:1058)
at org.codehaus.jackson.xc.JaxbAnnotationIntrospector.findDeserializer(JaxbAnnotationIntrospector.java:644)
at org.codehaus.jackson.xc.JaxbAnnotationIntrospector.findDeserializer(JaxbAnnotationIntrospector.java:74)
at org.codehaus.jackson.map.AnnotationIntrospector.findDeserializer(AnnotationIntrospector.java:634)
at org.codehaus.jackson.map.AnnotationIntrospector$Pair.findDeserializer(AnnotationIntrospector.java:1286)
有问题的依赖关系
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-bundle</artifactId>
<version>1.6</version>
</dependency>
<dependency>
<groupId>com.sun.jersey.contribs</groupId>
<artifactId>jersey-multipart</artifactId>
<version>1.6</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-server</artifactId>
<version>1.6</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.8.0</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-json</artifactId>
<version>1.6</version>
</dependency>
在你的情况下,Jackson 使用 class org.codehaus.jackson.xc.JaxbAnnotationIntrospector
到 deserialize/serialize ArrayList 和你的 POJO(我假设你在 web.xml 中配置了 com.sun.jersey.api.json.POJOMappingFeature
).
Jackson 正在寻找不存在的注释。请参阅 JaxbAnnotationIntrospector.java
中的第 643 行:
Class potentialAdaptee = ((Member)am.getAnnotated()).getDeclaringClass();
其中 am.getAnnotated()
是 null
。
因为您还没有 "annotated any of the beans with @XmlRootElement",一个简单的解决方案是禁用 JaxbAnnotationIntrospector
。这可以通过注册自定义 ContextResolver
提供自己的 ObjectMapper
实例来完成。
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.SerializationConfig.Feature;
import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;
@Provider
public class PojoObjectMapperProvider implements ContextResolver<ObjectMapper> {
final ObjectMapper defaultObjectMapper;
public PojoObjectMapperProvider() {
defaultObjectMapper = new ObjectMapper();
defaultObjectMapper.configure(Feature.INDENT_OUTPUT, true);
}
@Override
public ObjectMapper getContext(Class<?> type) {
return defaultObjectMapper;
}
}
要注册class:
import javax.ws.rs.core.Application;
import java.util.HashSet;
import java.util.Set;
public class MyApplication extends Application {
@Override
public Set<Class<?>> getClasses() {
final Set<Class<?>> classes = new HashSet<>();
classes.add(PojoObjectMapperProvider.class);
return classes;
}
}
如果你不使用 web.xml:
ApplicationAdapter rc = new ApplicationAdapter(new MyApplication());
rc.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
SelectorThread threadSelector = GrizzlyServerFactory.create(BASE_URI, rc);