json - Grails REST Client Builder在处理来自Jersey Web服务的响应时遇到JSON反序列化错误

标签 json rest grails jackson

我有一个Jersey网络服务,该服务生成/使用JSON,并使用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的响应,因为接受类型为“application / json”,我认为会尝试创建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客户端中更改以下各项的任意组合时,我得到的响应完全相同:
  • 完全不使用RestTemplate
  • 将RestTemplate与Only MappingJackson2HttpMessageConverter一起使用
  • 删除accept(“application / json”)
  • 删除contentType(“application / json”)

  • 这似乎无关紧要。无论我做什么,代码似乎都意识到它正在获取JSON并尝试反序列化。我真的不清楚为什么它试图反序列化为String。在服务器端没有可见的错误,并且由于该帖子可以完成,所以我不知道是否/如何检查我得到的响应。

    最佳答案

    我在代码中遇到了相同的错误(grails版本2.3.11和rest-client-builder版本2.0.0)。

    我将插件版本升级到“rest-client-builder:2.1.1”,该错误消失了。

    关于json - Grails REST Client Builder在处理来自Jersey Web服务的响应时遇到JSON反序列化错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29295346/

    相关文章:

    grails - 如何获取RememberMeServices的实例?

    java - 定义返回列表的 REST 端点

    javascript - JSON 文件错误

    javascript - console.log 如何确定打印对象时要打印哪些属性?

    flutter - 是否有用于通过 Google Pay (UPI) 创建付款请求的 REST API

    unit-testing - 在 grails 中使用 mockDomain 时如何覆盖方法的逻辑?

    grails - 如何显示HQL结果以便查看。

    java - 从 GWT ArrayList 中字符串化 JSON,然后返回数组

    bash - 使用 netcat nc 创建最小的 REST Web 服务器

    python - Rest 客户端的元语言