Spring Rest POST Json RequestBody Content type not supported
Asked Answered
R

17

70

When I try to post new object with post method. RequestBody could not recognize contentType. Spring is already configured and POST could work with others objects, but not this specific one.

org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/json;charset=UTF-8' not supported

If I try the same request just changing requestbody object. It works.

Rheinland answered 18/10, 2013 at 8:21 Comment(3)
you also get a slightly different error if you have not set Content type=application/jsonSchulz
There can be an issue with Jackson Deserializer. Refer LinkMandibular
There can be issue due to having multiple getters of field. Refer LinkMandibular
R
87

I found solution. It's was because I had 2 setter with same name but different type.

My class had id property int that I replaced with Integer when à Hibernitify my object.

But apparently, I forgot to remove setters and I had :

/**
 * @param id
 *            the id to set
 */
public void setId(int id) {
    this.id = id;
}

/**
 * @param id
 *            the id to set
 */
public void setId(Integer id) {
    this.id = id;
}

When I removed this setter, rest resquest work very well.

Intead to throw unmarshalling error or reflect class error. Exception HttpMediaTypeNotSupportedException seams really strange here.

I hope this stackoverflow could be help someone else.

SIDE NOTE

You can check your Spring server console for the following error message:

Failed to evaluate Jackson deserialization for type [simple type, class your.package.ClassName]: com.fasterxml.jackson.databind.JsonMappingException: Conflicting setter definitions for property "propertyname"

Then you can be sure you are dealing with the issue mentioned above.

Rheinland answered 18/10, 2013 at 8:22 Comment(5)
I spend like 5 hours on the very same problem. I had two setters on an entity called 'getSerial(...)'. One took a 'String' the other a 'BigInteger'...Prostomium
Same here... Had one for Enum and another one for String.. Thanks for this.Aback
Thank you for this. I couldn't track what was causing my error and that error message was much further up in my log than what I was checking. Searching for that deserialization error led me directly to the problem.Linalool
Clearly, the exception is inaccurate. One can figure out the actual error, by simply accepting the payload as a String and then try to Serialize the payload to your corresponding mapping Object.Roughhew
github.com/fasterxml/jackson-databind/issues/1044Gauleiter
R
8

Be aware also if you have declared getters and setters for attributes of the parameter which are not sent in the POST (event if they are not declared in the constructor), for example:

@RestController
public class TestController {

    @RequestMapping(value = "/test", method = RequestMethod.POST)
    public String test(@RequestBody BeanTest beanTest) {
        return "Hello " + beanTest.getName();
    }


    public static class BeanTest {

        private Long id;
        private String name;

        public BeanTest() {
        }

        public BeanTest(Long id) {
            this.id = id;
        }

        public Long getId() {
            return id;
        }

        public void setId(Long id) {
            this.id = id;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }
}

A post request with the next structure: {"id":"1"} would not work, you must delete name get and set.

Readymix answered 22/12, 2015 at 14:6 Comment(1)
Really? Does that mean all fields must be set?Querulous
C
6

If you use lombok, you can get that error if you screw up naming of @JsonDeserialize, for example:

@Value
@Builder(toBuilder = true)
@JsonDeserialize(builder = SomeClass.SomeOtherClassBuilder.class)
public class SomeClass {
    ...
    public static class SomeOtherClassBuilder {
        ...
    }
}

It should be:

@Value
@Builder(toBuilder = true)
@JsonDeserialize(builder = SomeClass.SomeClassBuilder.class)
public class SomeClass {
    ...
    public static class SomeClassBuilder {
        ...
    }
}

It is very easy to do that when you do refactoring of class name and forget about Builder... and then you have many hours of joy while you search for reason of error, while having as help only extremely unhelpful exception message.

Clubwoman answered 19/5, 2017 at 10:22 Comment(1)
In my case I was getting this issue because I used @JsonSerialize on a field but was missing the @JsonDeserialize annotation.Balneal
T
4

Really! after spending 4 hours and insane debugging I found this very strange code at com.fasterxml.jackson.databind.deser.DeserializerCache

if (deser == null) {
    try {
        deser = _createAndCacheValueDeserializer(ctxt, factory, type);
    } catch (Exception e) {
        return false;
    }
}

Ya, the problem was double setter.

Thankless answered 24/9, 2014 at 8:13 Comment(0)
T
2

I had the same issue when I had two setters one with Enum and one String. I had to use @JsonSetter annotation which tells Jackson what setter method to use during serialization. This solved my issue.

Trumaine answered 7/4, 2016 at 21:47 Comment(0)
C
2

I met the same problem which i solved by deserializing myself the posted value :

@RequestMapping(value = "/arduinos/commands/{idArduino}", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public String sendCommandesJson(@PathVariable("idArduino") String idArduino, HttpServletRequest request) throws IOException {
    // getting the posted value
    String body = CharStreams.toString(request.getReader());
    List<ArduinoCommand> commandes = new ObjectMapper().readValue(body, new TypeReference<List<ArduinoCommand>>() {
    });

with theses gradle dependencies :

  compile('org.springframework.boot:spring-boot-starter-web')
  compile('com.google.guava:guava:16.0.1')
Chloramine answered 16/6, 2016 at 12:10 Comment(0)
M
2

In my case I had two Constructors in the bean and I had the same error. I have just deleted one of them and now the issue is fixed!

Mice answered 21/6, 2016 at 12:6 Comment(0)
E
1

So I had a similar issue where I had a bean with some overloaded constructor. This bean also had Optional properties.

To resolve that I just removed the overloaded constructors and it worked.

example:

public class Bean{

Optional<String> string;
Optional<AnotherClass> object;

public Bean(Optional<String> str, Optional<AnotherClass> obj){
string = str;
object = obj;
}

///The problem was below constructor

public Bean(Optional<String> str){
string = str;
object = Optional.empty();
}



}

}
Engdahl answered 20/10, 2016 at 21:55 Comment(0)
R
1

It looks an old thread, but in case someone still struggles, I have solved as Thibaut said it,

Avoid having two setter POJO class, I had two-setters for a specific property , The first one was in the regular setter and another one in under constructor after I removed the one in the constructor it worked.

Rank answered 10/4, 2018 at 14:32 Comment(0)
C
1

specify @JsonProperty in entity class constructor like this.

......
......
......

 @JsonCreator
 public Location(@JsonProperty("sl_no") Long sl_no, 
          @JsonProperty("location")String location,
          @JsonProperty("location_type") String 
          location_type,@JsonProperty("store_sl_no")Long store_sl_no) {
  this.sl_no = sl_no;
  this.location = location;
  this.location_type = location_type;
  this.store_sl_no = store_sl_no;
 } 
.......
.......
.......
Complice answered 12/11, 2018 at 9:34 Comment(1)
should I import JsonProperty from com.fasterxml.jackson.annotation.* ?Shire
H
1

I had the same issue when I used this as a foreign key.

@JsonBackReference
@ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.DETACH},fetch = FetchType.EAGER)
@JoinColumn(name = "user_id")
private User user;

Then I removed @JsonBackReference annotation. After that above issue was fixed.

Hamamatsu answered 21/10, 2019 at 9:28 Comment(0)
P
1

I had this problem when using java 9+ modules. I had to open the module in order for the com.fasterxml.jackson.databind to access the objects with reflection. Alternatively you could only open the package where the models are located if you have one.

Platino answered 5/11, 2019 at 13:43 Comment(0)
M
1

For the case where there are 2 getters for the same property, the deserializer fails Refer Link

Mandibular answered 27/1, 2021 at 6:45 Comment(0)
E
0

try to add jackson dependency

    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-core</artifactId>
        <version>2.9.3</version>
    </dependency>

    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-annotations</artifactId>
        <version>2.9.3</version>
    </dependency>

    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.9.3</version>
        <exclusions>
            <exclusion>
                <artifactId>jackson-annotations</artifactId>
                <groupId>com.fasterxml.jackson.core</groupId>
            </exclusion>
        </exclusions>
    </dependency>
Evoy answered 27/2, 2018 at 12:45 Comment(0)
G
0

I had the same issue. Root cause was using custom deserializer without default constructor.

Gaeta answered 19/11, 2018 at 15:4 Comment(0)
F
0

In my case my function in the controller was annotated like this:

 @PatchMapping(path = "/{machineGroupName}", consumes = "application/json-patch+json")

Once I removed the "Consumes" parameter it worked.

Foolproof answered 25/8, 2021 at 13:51 Comment(0)
Q
0

Just adding request header

Content-Type: application/json

worked for me.

Querulous answered 2/8, 2022 at 15:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.