【问题标题】:Spring Rest POST Json RequestBody Content type not supported不支持 Spring Rest POST Json RequestBody 内容类型
【发布时间】:2013-10-27 00:19:28
【问题描述】:

当我尝试使用 post 方法发布新对象时。 RequestBody 无法识别 contentType。 Spring 已经配置,POST 可以与其他对象一起使用,但不是这个特定的对象。

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

如果我尝试相同的请求,只需更改 requestbody 对象。它有效。

【问题讨论】:

  • 如果你没有设置Content type=application/json,你也会得到一个稍微不同的错误
  • Jackson Deserializer 可能存在问题。参考Link
  • 由于有多个字段获取器,可能会出现问题。参考Link

标签: java json spring spring-mvc jackson


【解决方案1】:

我找到了解决方案。 这是因为我有两个同名但类型不同的二传手。

我的班级有 id 属性 int,当我休眠我的对象时,我将其替换为 Integer。

但显然,我忘了删除 setter,我有:

/**
 * @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;
}

当我删除这个 setter 时,rest resquest 工作得很好。

打算抛出解组错误或反映类错误。异常 HttpMediaTypeNotSupportedException 在这里接缝真的很奇怪。

我希望这个 stackoverflow 可以帮助其他人。

旁注

您可以检查您的 Spring 服务器 控制台以查看以下错误消息:

无法评估类型 [简单类型, 类 your.package.ClassName]: com.fasterxml.jackson.databind.JsonMappingException:冲突 属性“propertyname”的设置器定义

那么您可以确定您正在处理上述问题。

【讨论】:

  • 我在同一个问题上花了大约 5 个小时。我在一个名为“getSerial(...)”的实体上有两个设置器。一个拿了一个“字符串”,另一个拿了一个“BigInteger”……
  • 这里也一样...有一个用于枚举,另一个用于字符串。谢谢。
  • 谢谢你。我无法跟踪导致我的错误的原因,并且该错误消息在我的日志中比我正在检查的要多得多。搜索那个反序列化错误直接导致了我的问题。
  • 显然,异常是不准确的。可以通过简单地将有效负载作为字符串接受,然后尝试将有效负载序列化为相应的映射对象来找出实际错误。
【解决方案2】:

还要注意,如果您为参数的属性声明了 getter 和 setter,而这些属性未在 POST 中发送(如果它们未在构造函数中声明,则为事件),例如:

@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;
        }
    }
}

具有下一个结构的发布请求:{"id":"1"} 将不起作用,您必须删除名称获取和设置。

【讨论】:

    【解决方案3】:

    如果你使用 lombok,如果你搞砸了 @JsonDeserialize 的命名,你会得到这个错误,例如:

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

    应该是:

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

    当您重构类名并忘记 Builder 时,这样做很容易……然后您在寻找错误原因时有很多小时的快乐,而只有极其无用的异常消息作为帮助。

    【讨论】:

    • 在我的情况下,我遇到了这个问题,因为我在字段上使用了@JsonSerialize,但缺少@JsonDeserialize 注释。
    【解决方案4】:

    真的!在花了 4 个小时和疯狂的调试之后,我在 com.fasterxml.jackson.databind.deser.DeserializerCache 发现了这个非常奇怪的代码

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

    是的,问题是双重设置器。

    【讨论】:

      【解决方案5】:

      当我有两个 setter 一个 Enum 和一个 String 时,我遇到了同样的问题。我不得不使用@JsonSetter 注释,它告诉杰克逊在序列化过程中使用什么setter 方法。这解决了我的问题。

      【讨论】:

        【解决方案6】:

        我遇到了同样的问题,我通过反序列化自己的发布值来解决:

        @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>>() {
            });
        

        这些 gradle 依赖项:

          compile('org.springframework.boot:spring-boot-starter-web')
          compile('com.google.guava:guava:16.0.1')
        

        【讨论】:

          【解决方案7】:

          在我的例子中,我在 bean 中有两个构造函数并且我遇到了同样的错误。我刚刚删除了其中一个,现在问题已解决!

          【讨论】:

            【解决方案8】:

            所以我有一个类似的问题,我有一个带有一些重载构造函数的 bean。这个 bean 也有 Optional 属性。

            为了解决我刚刚删除了重载的构造函数并且它起作用了。

            示例:

            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();
            }
            
            
            
            }
            
            }
            

            【讨论】:

              【解决方案9】:

              看起来是老线程,但万一有人还在挣扎,我已经按照Thibaut说的解决了,

              避免有两个 setter POJO 类,我有两个用于特定属性的 setter,第一个在常规 setter 中,另一个在构造函数下,在我删除了它工作的构造函数中的一个之后。

              【讨论】:

                【解决方案10】:

                像这样在实体类构造函数中指定@JsonProperty。

                ......
                ......
                ......
                
                 @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;
                 } 
                .......
                .......
                .......
                

                【讨论】:

                • 我应该从 com.fasterxml.jackson.annotation.* 导入 JsonProperty 吗?
                【解决方案11】:

                当我将它用作外键时,我遇到了同样的问题。

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

                然后我删除了@JsonBackReference 注释。在上述问题得到解决之后。

                【讨论】:

                  【解决方案12】:

                  对于同一个属性有2个getter的情况,反序列化失败参考Link

                  【讨论】:

                    【解决方案13】:

                    尝试添加jackson依赖

                        <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>
                    

                    【讨论】:

                      【解决方案14】:

                      我有同样的问题。根本原因是使用没有默认构造函数的自定义反序列化器。

                      【讨论】:

                        【解决方案15】:

                        我在使用 java 9+ 模块时遇到了这个问题。我必须open 模块才能让com.fasterxml.jackson.databind 使用反射访问对象。或者,如果您有模型,则只能打开模型所在的包。

                        【讨论】:

                          【解决方案16】:

                          在我的例子中,我在控制器中的函数是这样注释的:

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

                          一旦我删除了“Consumes”参数,它就起作用了。

                          【讨论】:

                            猜你喜欢
                            • 1970-01-01
                            • 1970-01-01
                            • 2019-12-16
                            • 1970-01-01
                            • 2017-10-21
                            • 2016-11-17
                            • 1970-01-01
                            • 2018-11-06
                            • 2018-07-17
                            相关资源
                            最近更新 更多