搜索
简帛阁>技术文章>[踩坑] @RequestBody注解转换modal报400错误问题排查与解决

[踩坑] @RequestBody注解转换modal报400错误问题排查与解决

背景

最近在项目上开发接口时,controller接口选择用application/json方式接收参数,接口入参用了@RequestBody。简化controller和modal如下所示。

@RestController("/jsonModal")
public class JsonModalController {

    @PostMapping
    public Object json(@RequestBody JsonModal jsonModal) {
        return ResultAssistant.ok(jsonModal);
    }
}

public class JsonModal {

private String id;

private String name;

private int status;

public JsonModal(String id, String name, int status) {
this.id = id;
this.name = name;
this.status = status;
}

  ... 省略get,set
}

但是最终调试接口的时候总是报400状态码错误。

排查与解决

一开始以为是转换json字符串的格式不对,但后面用了fastJson进行json字符串转换后仍旧是400错误。

既然不是json字符串的问题,那就换个思路排查,首先需要找到具体的Exception。通过在项目的GlobalExceptionHandler的排查最终确定了此次异常为HttpMessageNotReadableException。

那么错误找到了,就开始分析为什么会出现这个错误,从该错误的注解来看,这个错误主要是在消息转换的出现错误的时候抛出的。

/**
 * Thrown by {@link HttpMessageConverter} implementations when the
 * {@link HttpMessageConverter#read} method fails.
 *
 * @author Arjen Poutsma
 * @since 3.0
 */
@SuppressWarnings("serial")
public class HttpMessageNotReadableException extends HttpMessageConversionException

那么接下来的事情自然就是打断点,跟踪排查了为什么在转换的时候会出现这个不可读的异常。通过断点追踪最后在jackson下的一个类解析器BeanDeserializerBase中发现如下的消息。

    protected Object deserializeFromObjectUsingNonDefault(JsonParser p,
            DeserializationContext ctxt) throws IOException
    {
        final JsonDeserializer delegateDeser = _delegateDeserializer();
        if (delegateDeser != null) {
            return _valueInstantiator.createUsingDelegate(ctxt,
                    delegateDeser.deserialize(p, ctxt));
        }
        if (_propertyBasedCreator != null) {
            return _deserializeUsingPropertyBased(p, ctxt);
        }
        // should only occur for abstract types...
        if (_beanType.isAbstract()) {
            return ctxt.handleMissingInstantiator(handledType(), p,
                    "abstract type (need to add/enable type information?)");
        }
        // 25-Jan-2017, tatu: We do not actually support use of Creators for non-static
        //   inner classes -- with one and only one exception; that of default constructor!
        //   -- so let's indicate it
        Class raw = _beanType.getRawClass();
        if (ClassUtil.isNonStaticInnerClass(raw)) {
            return ctxt.handleMissingInstantiator(raw, p,
"can only instantiate non-static inner class by using default, no-argument constructor");
        }
        return ctxt.handleMissingInstantiator(raw, p,
"no suitable constructor found, can not deserialize from Object value (missing default constructor or creator, or perhaps need to add/enable type information?)");
    } 
  
 

这个方法主要就是反序列化一个没有默认构造函数的bean,注意到后面注释之后的东西其实就已经说明了本次的问题了。

We do not actually support use of Creators for non-static inner classes -- with one and only one exception; that of default constructor! -- so let's indicate it

所以其实使用@RequestBody注解的参数其实是不支持使用静态内部class或者是一个没有默认构造函数的modal。

回到我自身使用的问题,可以看到我的modal是只有一个全参数构造函数而没有默认空构造函数,所以解决方案就是加一个空构造函数,问题即可解决。

总结

当使用@RequestBody注解入参的时候,记得注解后面紧跟的参数不要是一个static inner class或者是一个缺少空构造函数的class

转载于:https://www.cnblogs.com/magotzis/p/9605374.html

背景最近在项目上开发接口时,controller接口选择用application/json方式接收参数,接口入参用了@RequestBody。简化controller和modal如下所示。@RestC
一般使用@RequestBody接收的时候400都是传入的json字符串和对应封装的对象不对应造成的首先要注意封装的对象中的字段类型有没有Date类型或者int等类型的,如果有的话,在set方法中统
一般使用@RequestBody接收的时候400都是传入的json字符串和对应封装的对象不对应造成的首先要注意封装的对象中的字段类型有没有Date类型或者int等类型的,如果有的话,在set方法中统
一般使用@RequestBody接收的时候400都是传入的json字符串和对应封装的对象不对应造成的首先要注意封装的对象中的字段类型有没有Date类型或者int等类型的,如果有的话,在set方法中统
1、使用@RequestBody时,需要发送JSON格式的数据,请检查JSON格式数据是否正确,可以使用在线JSON工具校验,如果发送空的JSON数据,也要发送空的花括号,即“{}”;2、JSON数
使用@RequestBody时报400错误排查1、使用@RequestBody时,需要发送JSON格式的数据,请检查JSON格式数据是否正确,可以使用在线JSON工具校验,如果发送空的JSON数据
当我们在后端需要接收一个复杂对象或者一个list对象时,经常需要用到requestBody来帮助我们将请求参数绑定到我们接收的对象上,requestBody将请求参数变成json串放到body里面,这
参数不使用@RequestBody在使用Postman进行Post请求时,通常做法是填入key和value的值即可。参数使用@RequestBody使用@RequestBody注解时,在发送请求时,就
目录SpringMVC@RequestBody为null关于inputsteam的一些理解@RequestBody自动映射原理的简单介绍关于@requestBody的一些说明1、@requestBod
由于快过年的原因,项目组没有太多任务,闲来无事研究了一下spring中restful调用。发现spring竟然已经强大到如此境界,程序员已经不需要在关心在写接口的过程中数据的转换以及调用,只需要专注业