我有一个生成/使用JSON的Jersey Web服务,并使用Jackson进行POJO序列化/反序列化。我目前有一个基于Jersey API的客户端,以及一个基于Grails rest-client-builder插件的Groovy客户端。虽然Jersey客户端似乎没有问题,但我的Grails插件客户端在我正在处理的帖子请求上反序列化响应时出现问题。基于堆栈跟踪,似乎它正在尝试将响应正文中的JSON序列化为字符串由于某种原因?
org.springframework.http.converter.HttpMessageNotReadableException: Could not read JSON: Can not deserialize instance of java.lang.String out of START_OBJECT token
at [Source: sun.net.www.protocol.http.HttpURLConnection$HttpInputStream@239b0f9d; line: 1, column: 1]; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.lang.String out of START_OBJECT token
at [Source: sun.net.www.protocol.http.HttpURLConnection$HttpInputStream@239b0f9d; line: 1, column: 1]
at org.springframework.http.converter.json.MappingJackson2HttpMessageConverter.readJavaType(MappingJackson2HttpMessageConverter.java:228)
at org.springframework.http.converter.json.MappingJackson2HttpMessageConverter.read(MappingJackson2HttpMessageConverter.java:220)
at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:95)
at org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:795)
at org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:779)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:559)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:520)
at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:463)
以下是我的Jersey服务中资源的相关代码
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response addStory(Story s) {
if (null != s) {
//underlying DynamoDB client saves data to table
client.insertStory(s);
Response resp = Response.status(200).entity(s).build();
return resp;
}
else{
return Response.status(404).entity("No story data submitted").build();
}
}
对于基于Jersey API的客户端工作正常,这是相同的。
public class StoryServiceJerseyClient {
private static final Logger logger = LogManager.getLogger(StoryServiceJerseyClient.class.getName());
private static Client client = ClientBuilder.newClient().register(JacksonFeature.class);
WebTarget target = client.target("http://localhost:8080/jerseyexample/rest").path("/story");
public Story createStory(Story s){
Story storyPersisted = null;
storyPersisted = target
.request()
.post(Entity.entity(s, MediaType.APPLICATION_JSON),
Story.class);
return storyPersisted;
}
}
现在是Grails客户端。 我应该注意,所引用的Story类与上面的服务/客户端中的类不同。在大多数情况下,它包含相同的代码,并作为我正在检查的其他内容的临时解决方法存在。但我不认为这与问题有任何关系,因为在处理响应之前一切似乎都很好(因此类型似乎成功地通过序列化和正确转换)。该服务保存发送到DynamoDB表的数据,我看到发生成功。我不明白为什么它试图序列化对String的响应,我认为会尝试创建一个JSON对象,因为accept类型是“application / json”。
def addStory(Story story){
def restTemplate = new RestTemplate();
//experimented with adding/removing these/the explicit restTemplate
//but it hasn't had an effect
restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter())
restTemplate.getMessageConverters().add(new FormHttpMessageConverter())
restTemplate.getMessageConverters().add(new StringHttpMessageConverter())
def rest = new RestBuilder(restTemplate)
def resp = rest.post(STORY_RESOURCE_URI ){
accept("application/json")
contentType("application/json")
body(story)
}
def json = resp.json
return json
}
BuildConfig.groovy
dependencies {
...
compile "com.fasterxml.jackson.core:jackson-databind:2.5.1"
compile "com.fasterxml.jackson.core:jackson-core:2.5.1"
}
plugins {
...
compile ":rest-client-builder:2.1.0"
}
我正在使用Grails 2.4.4和Jersey 2.17。
更新 在尝试调试时我也注意到了一件事 - 我对json内容类型或消息转换器的引用似乎没有任何区别。当我在Grails客户端中更改以下任意组合时,我得到了完全相同的响应:
这一切似乎都不重要。无论我做什么,代码似乎都意识到它正在获取JSON并尝试反序列化。我真的不清楚为什么它试图反序列化为String。在服务器端没有可见的错误,由于帖子可以完成,我不知道是否可以检查我得到的响应。
答案 0 :(得分:1)
我的代码中出现了同样的错误(grails版本2.3.11和rest-client-builder版本2.0.0)。
我将插件版本升级为" rest-client-builder:2.1.1"而且虫子已经消失了。