之前使用springmvc搭建了restful风格的接口服务,在使用mockmvc进行集成测试的时候出现了异常:Can not deserialize instance of int out of START_OBJECT token。为什么会出现这个问题?怎么解决这个问题呢?接下来本文详细分析讲解这个问题。

一、问题展现

  1. 接口代码
@ResponseBody
@RequestMapping(value = "/m1", method = RequestMethod.POST)
@ApiOperation(value = "测试方法1", httpMethod = "POST", response = ApiResult.class, notes = "测试方法1")
public ApiResult method1(@ApiParam(required = true, name = "p1", value = "参数1") @RequestBody String p1,
@ApiParam(required = true, name = "p2", value = "参数2") @RequestBody Integer p2) throws Exception { String content = "p1=" + p1 + ", p2=" + p2;
System.out.println(content); ApiResult<String> result = new ApiResult<String>();
result.setCode(ResultCode.SUCCESS.getCode());
result.setData(content);
return result;
}
  1. 测试代码
@Test
public void method1Test() throws Exception {
Map<String, Object> params = new HashMap<String, Object>();
params.put("p1", "x001");
params.put("p2", 10010); ObjectMapper mapper = new ObjectMapper();
byte[] content = mapper.writeValueAsBytes(params);
this.mockMvc.perform(post("/activation/m1").contentType(APPLICATION_JSON_UTF8).content(content).accept(APPLICATION_JSON_UTF8))
.andExpect(status().isOk())
.andExpect(content().contentType(APPLICATION_JSON_UTF8))
.andExpect(jsonPath("$.code").value(2000))
.andDo(print()); }
  1. 执行上述测试代码控制台异常错误
Caused by: com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of int out of START_OBJECT token at [Source: org.springframework.mock.web.DelegatingServletInputStream@3e0fa1; line: 1, column: 1]
at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:148)
at com.fasterxml.jackson.databind.DeserializationContext.mappingException(DeserializationContext.java:762)
at com.fasterxml.jackson.databind.deser.std.StdDeserializer._parseInteger(StdDeserializer.java:419)
at com.fasterxml.jackson.databind.deser.std.NumberDeserializers$IntegerDeserializer.deserialize(NumberDeserializers.java:289)
at com.fasterxml.jackson.databind.deser.std.NumberDeserializers$IntegerDeserializer.deserialize(NumberDeserializers.java:271)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3066)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2221)
at org.springframework.http.converter.json.MappingJackson2HttpMessageConverter.readJavaType(MappingJackson2HttpMessageConverter.java:168)
... 50 more

二、分析问题

  我们先从接口方法中参数注解@RequestBody说起吧!我们大家都知道@ResponseBody是把接口方法返回结果转化成JSON形式提供给方法调用者,那么相对应的,@RequestBody是把客户端POST请求content部分转化成JavaBean对象或者JSON对象。@RequestBody的解析有两个条件:

  1. POST请求中content的值必须为json格式(存储形式可以是字符串,也可以是byte数组);
  2. 被@RequestBody注解的参数类型必须是完全可以接收参数值的类型,比如:Map,JSONObject,或者对应的JavaBean;

  @RequestBody将post请求中content值转为一个整体对象,该对象包含所有参数名和参数值,所以接口方法必须也是一个参数完全接收所有参数名和参数值。
根据上面展示的代码来看,@RequestBody将params对象json形式内容转换成一个整体参数值,无论是p1还是p2,都无法接收该参数值。

三、解决问题

  在method1方法中定义一个可以接收整体参数值的对象类型即可,通常可选类型有:Map、JSONObject和JavaBean,JSONObject相对于Map,其取值方法更灵活。下面我们将在method1方法中定义一个JSONObject类型的参数。

@ResponseBody
@RequestMapping(value = "/m1", method = RequestMethod.POST)
@ApiOperation(value = "测试方法1", httpMethod = "POST", response = ApiResult.class, notes = "测试方法1")
public ApiResult method1(@ApiParam(required = true, name = "p", value = "参数") @RequestBody JSONObject p) throws Exception { String content = "p1=" + p.getString("p1") + ", p2=" + p.getInt("p2");
System.out.println(content); ApiResult<String> result = new ApiResult<String>();
result.setCode(ResultCode.SUCCESS.getCode());
result.setData(content);
return result;
}

  测试响应结果正常:

MockHttpServletResponse:
Status = 200
Error message = null
Headers = {Content-Type=[application/json;charset=UTF-8]}
Content type = application/json;charset=UTF-8
Body = {"code":2000,"message":"","data":"p1=x001, p2=10010"}
Forwarded URL = null
Redirected URL = null
Cookies = []

四、扩展

  对POST接口的请求可以采取表单式和接口客户端式两种方法提交。

    1. 表单式提交
        参数形式:p1=v1&p2=v2,服务端接口方法获取参数可以采用@RequestParam注解对应参数方式。

    2. 客户端提交
        这里的客户端具体指自定义编码的客户端。将所有参数信息组织成一个整体对象,然后转换成json对象,设置为post请求content的值,提交到服务端。此时服务端接口方法获取参数即需要采用本文讨论的方式。其实本文method1方法也可以自定义一个包含p1和p2两个字段的JavaBean类型,自己可以尝试一下,呵呵!

http://javatech.wang/index.php/archives/82/

SpringMVC接口测试异常:Can not deserialize instance of int out of START_OBJECT token的更多相关文章

  1. JSON parse error: Cannot deserialize instance of `int` out of START_OBJECT token; nested exception is com.fasterxml.jackson.databind.exc

    代码程序: @PostMapping("selectById") @ResponseBody public Result selectById(@RequestBody int i ...

  2. Can not deserialize instance of xxx out of START_ARRAY token

    Json 反序列化异常 Failed to read HTTP message: org.springframework.http.converter.HttpMessageNotReadableEx ...

  3. Jackson反序列化提示:Can not deserialize instance of Task out of START_ARRAY token

    解决方法: 1.没有绝对的方法,只能不断的测试和排查. 2.检查一下JSON数据和实体的字段结构是不是不一致导致的.比如JSON数据是数组,而实体字段为非数组. 参考: https://stackov ...

  4. 关于fasterxml-jackson发生Can not deserialize instance of异常原因验证

    关于fasterxml-jackson发生Can not deserialize instance of异常原因验证 这两天线上有大量的java.lang.IllegalArgumentExcepti ...

  5. JSON parse error: Can not deserialize instance of java.lang.String out of START_OBJECT token; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of j

    异常信息如下: JSON parse error: Can not deserialize instance of java.lang.String out of START_OBJECT token ...

  6. SpringMVC 处理异常的4种方式

    springmvc处理异常有三种方式: 1.在一个controller中定义一个方法,用@ExceptionHandler注解标注.(优先级最高) @ExceptionHandler public M ...

  7. springmvc 通过异常增强返回给客户端统一格式

    在springmvc开发中,我们经常遇到这样的问题:逻辑正常执行时返回客户端指定格式的数据,比如json,但是遇NullPointerException空指针异常,NoSuchMethodExcept ...

  8. Could not read document: Can not deserialize instance of java.lang.String out of START_ARRAY

    线上问题: { "timestamp": "1544510665", "status": 400, "error": & ...

  9. 解决用户自生成meta导入kylin后报错问题Can not deserialize instance of java.lang.String[] out of VALUE_STRING token

    报错栈: -- ::, ERROR [http-bio--exec-] cube.CubeManager: : Error during load cube instance, skipping : ...

随机推荐

  1. linux命令大全(自己慢慢看)

    http://blog.zol.com.cn/874/article_873769.html rm -rf mydir /* 删除mydir目录 */ cd mydir /* 进入mydir目录 */ ...

  2. Gradle 1.12用户指南翻译——第四十章. ANTLR 插件

    本文由CSDN博客万一博主翻译,其他章节的翻译请参见: http://blog.csdn.net/column/details/gradle-translation.html 翻译项目请关注Githu ...

  3. ROS探索总结(十一)——机器视觉

    机器视觉在计算机时代已经越来越流行,摄像头价格越来越低廉,部分集成深度传感器的混合型传感器也逐渐在研究领域普及,例如微软推出的Kinect,而且与之配套的软件功能十分强大,为开发带来了极大的便利.RO ...

  4. 2018 .NET开发者调查报告: .NET Core 是怎么样的状态

    4月28日,在公众号里发起<.NET Core 使用调查>,该调查为期一周,有近3300名开发者参与. 已经使用.net core  的人数只有44%,计划使用.net core 比例达到 ...

  5. centos下 redmind2.6安装

    1.下载安装redmind有关软件 cd /tmp wget http://cache.ruby-lang.org/pub/ruby/2.1/ruby-2.1.5.tar.gz wget http:/ ...

  6. SVN服务器搭建和配置使用详解

    SVN服务器搭建和使用(一) Subversion是优秀的版本控制工具,其具体的的优点和详细介绍,这里就不再多说. 首先来下载和搭建SVN服务器. 现在Subversion已经迁移到apache网站上 ...

  7. DDD中直接引用和ID关联的关系

    聚合根到聚合根:通过ID关联: 聚合根到其内部的实体,直接引用: 聚合根到值对象,直接引用: 实体到聚合根: 通过ID关联 : 实体到其聚合的聚合根:1对1ID关联,1对多可直接引用 : 实体到其聚合 ...

  8. Failed building wheel for scandir 解决方案

    unbuntu 16.04 运行 pip install jupyter --upgrade 的时候出现了下面的错误 Failed building wheel for scandir Running ...

  9. Centos 7安装python3

    纯傻瓜式步骤,保证成功. 下面的操作,按照步骤来就可以了,不要在中途cd 到别的文件目录下,要想查看效果可以用 lsj加上对应的目录,不需要切换进去. 首先不管你当前在哪个目录下,输入以下命令. [r ...

  10. Sublime text 3 注册码激活码 版本号3143

    —– BEGIN LICENSE —– TwitterInc 200 User License EA7E-890007 1D77F72E 390CDD93 4DCBA022 FAF60790 61AA ...