使用 spring-boot-starter-web“无法找到可接受的表示”

我正在尝试使用 spring-boot-starter-web创建一个 rest 服务,该服务提供 Java 对象的 JSON 表示。据我所知,这个 boot-starter-web jar 应该能够自动处理通过 Jackson 到 JSON 的转换,但是我却得到了这个错误。

{
"timestamp": 1423693929568,
"status": 406,
"error": "Not Acceptable",
"exception": "org.springframework.web.HttpMediaTypeNotAcceptableException",
"message": "Could not find acceptable representation"
}

我的主管是..。

@RestController
@RequestMapping(value = "/media")
public class MediaController {
@RequestMapping(value = "/test", method = RequestMethod.POST)
public @ResponseBody UploadResult test(@RequestParam(value="data") final String data) {
String value = "hello, test with data [" + data + "]";
return new UploadResult(value);
}


@RequestMapping(value = "/test2", method = RequestMethod.POST)
public int test2() {
return 42;
}


@RequestMapping(value = "/test3", method = RequestMethod.POST)
public String test3(@RequestParam(value="data") final String data) {
String value = "hello, test with data [" + data + "]";
UploadResult upload = new UploadResult(value);
return upload.value;
}




public static class UploadResult {
private String value;
public UploadResult(final String value)
{
this.value = value;
}
}
}

我的 pom.xml已经..。

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>1.2.1.RELEASE</version>
</dependency>


<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<version>1.2.1.RELEASE</version>
<scope>provided</scope>
</dependency>

mvn dependency:tree表明 spring-boot-starter-web 确实依赖 jackson2.4数据绑定,因此应该位于类路径上..。

[INFO] +- org.springframework.boot:spring-boot-starter-web:jar:1.2.1.RELEASE:compile
[INFO] |  +- org.springframework.boot:spring-boot-starter:jar:1.2.1.RELEASE:compile
[INFO] |  |  +- org.springframework.boot:spring-boot:jar:1.2.1.RELEASE:compile
[INFO] |  |  +- org.springframework.boot:spring-boot-autoconfigure:jar:1.2.1.RELEASE:compile
[INFO] |  |  +- org.springframework.boot:spring-boot-starter-logging:jar:1.2.1.RELEASE:compile
[INFO] |  |  |  +- org.slf4j:jul-to-slf4j:jar:1.7.8:compile
[INFO] |  |  |  \- org.slf4j:log4j-over-slf4j:jar:1.7.8:compile
[INFO] |  |  \- org.yaml:snakeyaml:jar:1.14:runtime
[INFO] |  +- com.fasterxml.jackson.core:jackson-databind:jar:2.4.4:compile
[INFO] |  |  +- com.fasterxml.jackson.core:jackson-annotations:jar:2.4.0:compile
[INFO] |  |  \- com.fasterxml.jackson.core:jackson-core:jar:2.4.4:compile
[INFO] |  +- org.hibernate:hibernate-validator:jar:5.1.3.Final:compile
[INFO] |  |  +- javax.validation:validation-api:jar:1.1.0.Final:compile
[INFO] |  |  +- org.jboss.logging:jboss-logging:jar:3.1.3.GA:compile
[INFO] |  |  \- com.fasterxml:classmate:jar:1.0.0:compile
[INFO] |  +- org.springframework:spring-web:jar:4.1.4.RELEASE:compile
[INFO] |  |  +- org.springframework:spring-aop:jar:4.1.4.RELEASE:compile
[INFO] |  |  |  \- aopalliance:aopalliance:jar:1.0:compile
[INFO] |  |  +- org.springframework:spring-beans:jar:4.1.4.RELEASE:compile
[INFO] |  |  \- org.springframework:spring-context:jar:4.1.4.RELEASE:compile
[INFO] |  \- org.springframework:spring-webmvc:jar:4.1.4.RELEASE:compile
[INFO] |     \- org.springframework:spring-expression:jar:4.1.4.RELEASE:compile

但是调用 test服务会出现上面提到的错误。test2test3工作良好,证明它必须只是尝试转换到 JSON 失败?我是否遗漏了一些配置问题或注释?从我能找到的所有示例中,不再需要为基本 Jackson JSON 转换注释类。

非常感谢你的帮助。

242877 次浏览

You have no public getters for your UpdateResult, for example :

public static class UploadResult {
private String value;
public UploadResult(final String value)
{
this.value = value;
}


public String getValue() {
return this.value;
}
}

I believe by default auto discovery is on and will try to discover your getters. You can disable it with @JsonAutoDetect(getterVisibility=Visibility.NONE), and in your example will result in [].

I had a similar error using spring/jhipster RESTful service (via Postman)

The endpoint was something like:

@RequestMapping(value = "/index-entries/{id}",
method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE)
@Timed
public ResponseEntity<IndexEntry> getIndexEntry(@PathVariable Long id) {

I was attempting to call the restful endpoint via Postman with header Accept: text/plain but I needed to use Accept: application/json

Add below dependency to your pom.xml:

<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
<version>2.10.2</version>
</dependency>

My return object didn't have @XmlRootElement annotation on the class. Adding the annotation solved my issue.

@XmlRootElement(name = "ReturnObjectClass")
public class ReturnObjectClass {


@XmlElement(name = "Status", required = true)
protected StatusType status;
//...
}

I had to explicitly call out the dependency for my json library in my POM.

Once I added the below dependency, it all worked.

<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</dependency>

If using @FeignClient, add e.g.

produces = "application/json"

to the @RequestMapping annotation

I too was facing a similar issue. In my case the request path was accepting mail id as path variable, so the uri looked like /some/api/test@test.com

And based on path, Spring determined the uri is to fetch some file with ".com" extension and was trying to use different media type for response then intended one. After making path variable into request param it worked for me.

accepted answer is not right with Spring 5. try changing your URL of your web service to .json! that is the right fix. great details here http://stick2code.blogspot.com/2014/03/solved-orgspringframeworkwebhttpmediaty.html

I had the same exception but the cause was different and I couldn't find any info on that so I will post it here. It was just a simple to overlook mistake.

Bad:

@RestController(value = "/api/connection")

Good:

@RestController
@RequestMapping(value = "/api/connection")

In my case I happened to be using lombok and apparently there are conflicts with the get and set

I had the same exception. The problem was, that I used the annotation

@RepositoryRestController

instead of

@RestController

I had this issue when accessing actuator. Putting following configuration class solved the issue:

@Configuration
@EnableWebMvc
public class MediaConverterConfiguration implements WebMvcConfigurer {
@Bean
public MappingJackson2HttpMessageConverter jacksonConverter() {
MappingJackson2HttpMessageConverter mc =
new MappingJackson2HttpMessageConverter();
List<MediaType> supportedMediaTypes =
new ArrayList<>(mc.getSupportedMediaTypes());
supportedMediaTypes
.add(MediaType.valueOf(MediaType.APPLICATION_JSON_VALUE));
supportedMediaTypes.add(
MediaType.valueOf("application/vnd.spring-boot.actuator.v2+json"));
mc.setSupportedMediaTypes(supportedMediaTypes);
return mc;
}


@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(jacksonConverter());
}
}

Had similar issue when one of my controllers was intercepting all requests with empty @GetMapping

I got the exact same problem. After viewing this reference: https://zetcode.com/springboot/requestparam/

My problem solved by changing

method = RequestMethod.GET, produces = "application/json;charset=UTF-8"

to

method = RequestMethod.GET, produces = MediaType.TEXT_PLAIN_VALUE

and don't forget to add the library:

import org.springframework.http.MediaType;

it works on both postman or regular browser.

If you are using Lombok, make sure it have annotations like @Data or @Getter @Setter in your Response Model class.

In my case I was sending in correct object in ResponseEntity<>().

Correct :

@PostMapping(value = "/get-customer-details", produces = { MediaType.APPLICATION_JSON_VALUE })
public ResponseEntity<?> getCustomerDetails(@RequestBody String requestMessage) throws JSONException {
JSONObject jsonObject = new JSONObject();
jsonObject.put("customerId", "123");
jsonObject.put("mobileNumber", "XXX-XXX-XXXX");
return new ResponseEntity<>(jsonObject.toString(), HttpStatus.OK);
}

Incorrect :

return new ResponseEntity<>(jsonObject, HttpStatus.OK);

Because, jsonObject's toString() method "Encodes the jsonObject as a compact JSON string". Therefore, Spring returns json string directly without any further serialization.

When we send jsonObject instead, Spring tries to serialize it based on produces method used in RequestMapping and fails due to it "Could not find acceptable representation".

For me, the problem was trying to pass a filename in a url, with a dot. For example

"http://localhost:8080/something/asdf.jpg" //causes error because of '.jpg'

It could be solved by not passing the .jpg extension, or sending it all in a request body.

I was running into the same issue, and what I was missing in my setup was including this in my maven (pom.xml) file.

<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.9</version>
</dependency>

Even if you do all of the above, as like in my case I still got the error 406 - Not acceptable when used from postman. Upon careful study, I have noticed that, in the request headers, default header for 'accept' is '/'.

I solved my problem, by adding a preset to the header and switched off default header. Please see below screenshot.

screenshot of postman preset

This solved my problem without any other settings or even adding the spring configurations.

if you are using postman to test, trying to check out the Header. my mistake was I'm using application/xml instead of application/json in "Accept" row.

Spent the whole day on this because none of the suggestions worked for me. Alas, it was the WebConfig implementation; specifically the configurer.ignoreAcceptHeader(true) that was the culprit preventing the .yaml from generating.

Hope this helps someone.

I encountered same exception: "Resolved [org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation"]

In analysis I fount that this problem can generate during serialization of a class while calling a @Controller or @RestController.

In serialization, if you are using class, it must have public Setter and Getter.

In the project where it occurs I found that a getter method was private and because of that this problem occurred.