当前位置: 首页 > 知识库问答 >
问题:

无法写入请求:找不到适合请求类型[org.json.JSONObject]和内容类型[应用程序/json]的HttpMessageConverter

程举
2023-03-14

我正在努力将带有JSON有效负载的POST请求发送到远程服务器。

此GET curl命令工作正常:

curl -H "Accept:application/json" --user aaa@aaa.com:aaa "http://www.aaa.com:8080/aaa-project-rest/api/users/1" -i

这个POST也很好:

curl -H "Accept:application/json" -H "Content-Type: application/json" "http://www.aaa.com:8080/aaa-project-rest/api/users/login" -X POST -d "{ \"email\" : \"aaa@aaa.com\", \"password\" : \"aaa\" }" -i

所以我试着在我的Android应用程序中模仿它。

该应用程序在第一个GET请求上运行良好,但在第二个POST请求上发出400个错误请求。

下面是用于GET请求的代码:

  RestTemplate restTemplate = new RestTemplate();
  restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
  HttpHeaders httpHeaders = Common.createAuthenticationHeaders("aaa@aaa.com" + ":" + "aaa");
  User user = null;
  ResponseEntity<User> responseEntity = restTemplate.exchange("http://" + REST_HOST + ":8080/aaa-project-rest/api/users/" + 1L, HttpMethod.GET, new HttpEntity<Object>(httpHeaders), User.class);

以下是POST请求的源代码:

RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
User user = null;
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
httpHeaders.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
JSONObject jsonCredentials = new JSONObject();
jsonCredentials.put("email", REST_LOGIN);
jsonCredentials.put("password", REST_PASSWORD);
ResponseEntity<User> responseEntity = restTemplate.exchange("http://" + REST_HOST + ":" + REST_PORT + "/" + REST_APP + "/api/users/login",
        HttpMethod.POST, new HttpEntity<Object>(jsonCredentials, httpHeaders), User.class);

但它传达了这样一个信息:

Could not write request: no suitable HttpMessageConverter found for request type [org.json.JSONObject] and content type [application/json]

这是Spring座控制器:

@RequestMapping(value = RESTConstants.SLASH + RESTConstants.LOGIN, method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public ResponseEntity<UserResource> login(@Valid @RequestBody CredentialsResource credentialsResource, UriComponentsBuilder builder) {
    HttpHeaders responseHeaders = new HttpHeaders();
    User user = credentialsService.checkPassword(credentialsResource);
    userService.clearReadablePassword(user);
    if (user == null) {
        return new ResponseEntity<UserResource>(responseHeaders, HttpStatus.NOT_FOUND);
    } else {
        tokenAuthenticationService.addTokenToResponseHeader(responseHeaders, credentialsResource.getEmail());
        responseHeaders.setLocation(builder.path(RESTConstants.SLASH + RESTConstants.USERS + RESTConstants.SLASH + "{id}").buildAndExpand(user.getId()).toUri());
        UserResource createdUserResource = userResourceAssembler.toResource(user);
        ResponseEntity<UserResource> responseEntity = new ResponseEntity<UserResource>(createdUserResource, responseHeaders, HttpStatus.CREATED);
        return responseEntity;
    }
}

@RequestMapping(value = RESTConstants.SLASH + "{id}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public ResponseEntity<UserResource> findById(@PathVariable Long id, UriComponentsBuilder builder) {
    HttpHeaders responseHeaders = new HttpHeaders();
    User user = userService.findById(id);
    if (user == null) {
        return new ResponseEntity<UserResource>(responseHeaders, HttpStatus.NOT_FOUND);
    } else {
        UserResource userResource = userResourceAssembler.toResource(user);
        responseHeaders.setLocation(builder.path(RESTConstants.SLASH + RESTConstants.USERS + RESTConstants.SLASH + "{id}").buildAndExpand(user.getId()).toUri());
        ResponseEntity<UserResource> responseEntity = new ResponseEntity<UserResource>(userResource, responseHeaders, HttpStatus.OK);
        return responseEntity;
    }
}

凭据资源类代码:

public class CredentialsResource extends ResourceSupport {

    @NotEmpty
    @Email
    private String email;
    @NotEmpty
    private String password;

    public CredentialsResource() {
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

}

共有3个答案

杨鸿畅
2023-03-14

如果类路径中不存在JSON实现,则引发异常“找不到合适的HTTPMessageConverter”。查看RestTemplate源代码:

public RestTemplate() {
    this.messageConverters.add(new ByteArrayHttpMessageConverter());
    this.messageConverters.add(new StringHttpMessageConverter());
    this.messageConverters.add(new ResourceHttpMessageConverter());
    this.messageConverters.add(new SourceHttpMessageConverter<Source>());
    this.messageConverters.add(new AllEncompassingFormHttpMessageConverter());

    if (romePresent) {
        this.messageConverters.add(new AtomFeedHttpMessageConverter());
        this.messageConverters.add(new RssChannelHttpMessageConverter());
    }

    if (jackson2XmlPresent) {
        this.messageConverters.add(new MappingJackson2XmlHttpMessageConverter());
    }
    else if (jaxb2Present) {
        this.messageConverters.add(new Jaxb2RootElementHttpMessageConverter());
    }

    if (jackson2Present) {
        this.messageConverters.add(new MappingJackson2HttpMessageConverter());
    }
    else if (gsonPresent) {
        this.messageConverters.add(new GsonHttpMessageConverter());
    }
}

将JSON实现添加到您的类路径中。例如:

implementation "com.fasterxml.jackson.core:jackson-databind:2.9.0"
李文轩
2023-03-14

我必须做几件事才能让它工作起来。

首先,我必须将JSONObject转换为字符串,如下所示:

HttpEntity<String> entityCredentials = new HttpEntity<String>(jsonCredentials.toString(), httpHeaders);

原因是JSONObject类没有映射消息转换器,而String类有一个。

其次,我必须向RestTemplate构造函数传递一个真值。如果不这样做,我会收到400个错误的请求。

RestTemplate restTemplate = new RestTemplate(true);

true值告诉rest模板使用默认转换器。如果有人知道为什么会这样,我很乐意了解更多。

第三,我移除了不需要的Jackson转换器:

restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());

完成这些工作后,请求就可以正常工作了。

以下是完整代码:

RestTemplate restTemplate = new RestTemplate(true);    
User user = null;
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
httpHeaders.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
try {
    JSONObject jsonCredentials = new JSONObject();
    jsonCredentials.put("email", REST_LOGIN);
    jsonCredentials.put("password", REST_PASSWORD);
    Log.e(Constants.APP_NAME, ">>>>>>>>>>>>>>>> JSON credentials " + jsonCredentials.toString());
    HttpEntity<String> entityCredentials = new HttpEntity<String>(jsonCredentials.toString(), httpHeaders);
    ResponseEntity<User> responseEntity = restTemplate.exchange("http://" + REST_HOST + ":" + REST_PORT + "/" + REST_APP + "/api/users/login",
            HttpMethod.POST, entityCredentials, User.class);
    if (responseEntity != null) {
        user = responseEntity.getBody();
    }
    return user;
} catch (Exception e) {
    Log.e(Constants.APP_NAME, ">>>>>>>>>>>>>>>> " + e.getLocalizedMessage());
}
return null;

我怀疑可能有一种方法可以显式使用Jackson转换器并跳过rest模板构造函数中的真值,但这只是一种猜测。

商兴朝
2023-03-14

虽然我刚刚遇到了同样的问题,并花了一些时间来解决它,但回复得很晚。所以,我想我最好分享它,并跟踪我的解决方案

实际上,抛出的异常完全具有误导性。事实证明,问题不在于MappingJackson2HttpMessageConverter不知道如何管理我的对象——这听起来很奇怪,是JSON——而是底层ObjectMapper的配置。

我所做的是禁用属性SerializationFeature。FAIL_ON_EMPTY_BEANS像这样

restTemplate = new RestTemplate();
MappingJackson2HttpMessageConverter jsonHttpMessageConverter = new MappingJackson2HttpMessageConverter();
jsonHttpMessageConverter.getObjectMapper().configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
restTemplate.getMessageConverters().add(jsonHttpMessageConverter);

一切开始按预期进行。

 类似资料:
  • 我试图发送一个POST请求到REST服务使用REST模板,但得到下面的错误 RestClientException:无法写入请求:找不到适合请求类型[xxx.query.XBrainQueryRequest]和内容类型[application/json]的HttpMessageConverter。 我的XBrainQueryRequest课程如下 有人能解释我为什么会出错以及如何解决它吗?我对这些

  • 我想实现使用Spring Cloud的客户端请求。我试过这个: 外国客户: 请求DTO: 控制器: 外型: 但是当我发出POST请求时,我得到了例外: 你知道我怎样才能解决这个问题吗?

  • 问题内容: 我有一个烧瓶应用程序,具有以下视图: 但是,这仅在请求的内容类型设置为时才有效,否则dict 为None。 我知道请求主体为字符串,但我不想每次客户端忘记设置请求的内容类型时都将其解析为字典。 有没有办法假设每个传入请求的content- type是?我想要的就是始终访问有效的字典,即使客户端忘记将应用程序的内容类型设置为json。 问题答案: 使用并设置为: 从文档中: 默认情况下,

  • 问题内容: 我有一个宁静的服务(发布),它消耗(application / json)并产生(application / json)。此服务的单个参数是带注释的java对象。 我正在使用org.jboss.resteasy.client.ClientRequest将请求发送到服务。但是,我在客户端得到了这个异常和异常: 找不到内容类型应用程序/ json类型的编写器。 这是否意味着我缺少一些库ja

  • 我使用Maven Spring 4.1。0 Java 6,我想使用RestTemplate()。postForEntity(url、请求、响应类型) 当我执行这段代码时: 但是我有这个错误: 组织。springframework。http。转换器。HttpMessageGenetWritableException:无法写入请求:在org上找不到适用于请求类型[java.util.HashMap]的

  • 我正在向另一个服务发送GET请求,该服务以以下格式返回: 我以这种方式使用响应实体: 然而,当发送GET请求时,我得到了这个响应:类型定义错误:[简单类型,类com.tdl.model.ArrayResponsePojo];嵌套异常是com.tdl.model.ArrayResponsePojo 我不知道为什么我会得到这个解释,因为我确实有构造器。这是我的pojo类: 和我的用户类: 我尝试了没有