在 Spring MVC 中使用 JAXB 注释与 Jackson 进行反序列化时出现问题
在调用服务时,我无法让 Jackson 正确地将 json 反序列化为对象(具体来说,我们正在使用 Jackson 的 JAXB 注释功能,因为我们还希望服务使用 XML)。我正在使用 Spring MVC,并使用 RestTemplate 类来调用服务。
这是我为我的 junit 设置 MappingJacksonHttpMessageConverter 的地方:
ObjectMapper jsonMapper = new ObjectMapper();
AnnotationIntrospector introspector = new JaxbAnnotationIntrospector();
jsonMapper.getDeserializationConfig().setAnnotationIntrospector(introspector);
jsonMapper.getSerializationConfig().setAnnotationIntrospector(introspector);
jsonMapper.getSerializationConfig().setSerializationInclusion(Inclusion.NON_NULL);
MappingJacksonHttpMessageConverter jacksonConverter = new MappingJacksonHttpMessageConverter();
jacksonConverter.setObjectMapper(jsonMapper);
List<HttpMessageConverter<?>> converters = new ArrayList<HttpMessageConverter<?>>();
converters.add(jacksonConverter);
template.setMessageConverters(converters);
我像这样调用该服务:
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.set("Accept", "application/json");
HttpEntity<String> requestEntity = new HttpEntity<String>(requestHeaders);
ResponseEntity<NamedSystem> responseEntity = template.exchange(baseURL + "/{NamedSystemId}",
HttpMethod.GET, requestEntity, NamedSystem.class, orgId1);
我的 NamedSystem
类的设置如下:
@XmlRootElement(name = "NamedSystem", namespace = "http://schemas.abc.workplace.com/NamedSystem")
public class NamedSystem {
private String id;
private String name;
private String description;
private Set<NamedSystemAlias> aliases;
private String href;
@XmlAttribute(required = false, name = "id")
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
@XmlAttribute(required = false, name = "name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@XmlAttribute(required = false, name = "description")
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
@XmlElementWrapper(required = false, name = "aliases", namespace = "http://schemas.abc.workplace.com/NamedSystem")
@XmlElement(required = false, name = "alias", namespace = "http://schemas.abc.workplace.com/NamedSystem")
public Set<NamedSystemAlias> getAliases() {
return aliases;
}
public void setAliases(Set<NamedSystemAlias> aliases) {
this.aliases = aliases;
}
@XmlAttribute(required = true, name = "href")
public String getHref() {
return href;
}
public void setHref(String href) {
this.href = href;
}
}
这是导致的错误:
org.springframework.web.client.ResourceAccessException: I/O error: Unrecognized field "NamedSystem" (Class com.workplace.abc.named.NamedSystem), not marked as ignorable
at [Source: sun.net.www.protocol.http.HttpURLConnection$HttpInputStream@c1429c; line: 1, column: 2]; nested exception is org.codehaus.jackson.map.JsonMappingException: Unrecognized field "NamedSystem" (Class com.workplace.abc.named.NamedSystem), not marked as ignorable
at [Source: sun.net.www.protocol.http.HttpURLConnection$HttpInputStream@c1429c; line: 1, column: 2]
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:453)
....
Caused by: org.codehaus.jackson.map.JsonMappingException: Unrecognized field "NamedSystem" (Class com.workplace.abc.named.NamedSystem), not marked as ignorable
at [Source: sun.net.www.protocol.http.HttpURLConnection$HttpInputStream@c1429c; line: 1, column: 2]
at org.codehaus.jackson.map.JsonMappingException.from(JsonMappingException.java:159)
at org.codehaus.jackson.map.deser.StdDeserializationContext.unknownFieldException(StdDeserializationContext.java:247)
at org.codehaus.jackson.map.deser.StdDeserializer.reportUnknownProperty(StdDeserializer.java:366)
at org.codehaus.jackson.map.deser.StdDeserializer.handleUnknownProperty(StdDeserializer.java:352)
at org.codehaus.jackson.map.deser.BeanDeserializer.handleUnknownProperty(BeanDeserializer.java:543)
at org.codehaus.jackson.map.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:402)
at org.codehaus.jackson.map.deser.BeanDeserializer.deserialize(BeanDeserializer.java:287)
at org.codehaus.jackson.map.ObjectMapper._readMapAndClose(ObjectMapper.java:1588)
at org.codehaus.jackson.map.ObjectMapper.readValue(ObjectMapper.java:1172)
at org.springframework.http.converter.json.MappingJacksonHttpMessageConverter.readInternal(MappingJacksonHttpMessageConverter.java:132)
at org.springframework.http.converter.AbstractHttpMessageConverter.read(AbstractHttpMessageConverter.java:154)
at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:74)
at org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:619)
at org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:1)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:446)
... 32 more
它似乎无法识别rootElement 'NamedSystem' 能够反序列化。我怎样才能让它做到这一点?我见过使用相同 JAXB 注释的示例,并且它们工作正常,因此我不确定我的情况有什么不同,或者我不确定如何强制它正确反序列化。如果有人可以提供任何帮助,我将不胜感激。
I'm having trouble getting Jackson to correctly deserialize json into an object when calling a service (specifically we're using Jackson's ability to use JAXB annotations since we also want the service to use XML). I'm using Spring MVC and I'm using the RestTemplate class to make calls to the service.
Here is where I setup the MappingJacksonHttpMessageConverter for my junit:
ObjectMapper jsonMapper = new ObjectMapper();
AnnotationIntrospector introspector = new JaxbAnnotationIntrospector();
jsonMapper.getDeserializationConfig().setAnnotationIntrospector(introspector);
jsonMapper.getSerializationConfig().setAnnotationIntrospector(introspector);
jsonMapper.getSerializationConfig().setSerializationInclusion(Inclusion.NON_NULL);
MappingJacksonHttpMessageConverter jacksonConverter = new MappingJacksonHttpMessageConverter();
jacksonConverter.setObjectMapper(jsonMapper);
List<HttpMessageConverter<?>> converters = new ArrayList<HttpMessageConverter<?>>();
converters.add(jacksonConverter);
template.setMessageConverters(converters);
And I call the service like so:
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.set("Accept", "application/json");
HttpEntity<String> requestEntity = new HttpEntity<String>(requestHeaders);
ResponseEntity<NamedSystem> responseEntity = template.exchange(baseURL + "/{NamedSystemId}",
HttpMethod.GET, requestEntity, NamedSystem.class, orgId1);
My NamedSystem
class is set up like so:
@XmlRootElement(name = "NamedSystem", namespace = "http://schemas.abc.workplace.com/NamedSystem")
public class NamedSystem {
private String id;
private String name;
private String description;
private Set<NamedSystemAlias> aliases;
private String href;
@XmlAttribute(required = false, name = "id")
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
@XmlAttribute(required = false, name = "name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@XmlAttribute(required = false, name = "description")
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
@XmlElementWrapper(required = false, name = "aliases", namespace = "http://schemas.abc.workplace.com/NamedSystem")
@XmlElement(required = false, name = "alias", namespace = "http://schemas.abc.workplace.com/NamedSystem")
public Set<NamedSystemAlias> getAliases() {
return aliases;
}
public void setAliases(Set<NamedSystemAlias> aliases) {
this.aliases = aliases;
}
@XmlAttribute(required = true, name = "href")
public String getHref() {
return href;
}
public void setHref(String href) {
this.href = href;
}
}
This is the error that results:
org.springframework.web.client.ResourceAccessException: I/O error: Unrecognized field "NamedSystem" (Class com.workplace.abc.named.NamedSystem), not marked as ignorable
at [Source: sun.net.www.protocol.http.HttpURLConnection$HttpInputStream@c1429c; line: 1, column: 2]; nested exception is org.codehaus.jackson.map.JsonMappingException: Unrecognized field "NamedSystem" (Class com.workplace.abc.named.NamedSystem), not marked as ignorable
at [Source: sun.net.www.protocol.http.HttpURLConnection$HttpInputStream@c1429c; line: 1, column: 2]
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:453)
....
Caused by: org.codehaus.jackson.map.JsonMappingException: Unrecognized field "NamedSystem" (Class com.workplace.abc.named.NamedSystem), not marked as ignorable
at [Source: sun.net.www.protocol.http.HttpURLConnection$HttpInputStream@c1429c; line: 1, column: 2]
at org.codehaus.jackson.map.JsonMappingException.from(JsonMappingException.java:159)
at org.codehaus.jackson.map.deser.StdDeserializationContext.unknownFieldException(StdDeserializationContext.java:247)
at org.codehaus.jackson.map.deser.StdDeserializer.reportUnknownProperty(StdDeserializer.java:366)
at org.codehaus.jackson.map.deser.StdDeserializer.handleUnknownProperty(StdDeserializer.java:352)
at org.codehaus.jackson.map.deser.BeanDeserializer.handleUnknownProperty(BeanDeserializer.java:543)
at org.codehaus.jackson.map.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:402)
at org.codehaus.jackson.map.deser.BeanDeserializer.deserialize(BeanDeserializer.java:287)
at org.codehaus.jackson.map.ObjectMapper._readMapAndClose(ObjectMapper.java:1588)
at org.codehaus.jackson.map.ObjectMapper.readValue(ObjectMapper.java:1172)
at org.springframework.http.converter.json.MappingJacksonHttpMessageConverter.readInternal(MappingJacksonHttpMessageConverter.java:132)
at org.springframework.http.converter.AbstractHttpMessageConverter.read(AbstractHttpMessageConverter.java:154)
at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:74)
at org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:619)
at org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:1)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:446)
... 32 more
It seems it doesn't recognize the rootElement 'NamedSystem' to be able to deserialize. How would I get it to do that? I've seen examples that use the same JAXB annotations and they work fine so I'm not sure what's different about my case or how I might force it to correctly deserialize it. If anyone can offer any help, I'd appreciate it.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
如果有人遇到此类问题,这可能会为您解决:使 Jackson 在序列化时不输出类名(使用 Spring MVC)
请参阅我的答案并点击链接查看示例。
If anyone comes along this kind of problem, this might fix it for you: Enable Jackson to not output the class name when serializing (using Spring MVC)
See my answer and follow the link for an example.