以前使用springmvc搭建了restful風格的接口服務,在使用mockmvc進行集成測試的時候出現了異常:Can not deserialize instance of int out of START_OBJECT token。爲何會出現這個問題?怎麼解決這個問題呢?接下來本文詳細分析講解這個問題。 php
@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; }
@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()); }
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的解析有兩個條件: java
@RequestBody將post請求中content值轉爲一個總體對象,該對象包含全部參數名和參數值,因此接口方法必須也是一個參數徹底接收全部參數名和參數值。根據上面展現的代碼來看,@RequestBody將params對象json形式內容轉換成一個總體參數值,不管是p1仍是p2,都沒法接收該參數值。 web
在method1方法中定義一個能夠接收總體參數值的對象類型便可,一般可選類型有:Map、JSONObject和JavaBean,JSONObject相對於Map,其取值方法更靈活。下面咱們將在method1方法中定義一個JSONObject類型的參數。 spring
@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; }
測試響應結果正常: json
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接口的請求能夠採起表單式和接口客戶端式兩種方法提交。 數組
表單式提交
參數形式:p1=v1&p2=v2,服務端接口方法獲取參數能夠採用@RequestParam註解對應參數方式。 restful
客戶端提交
這裏的客戶端具體指自定義編碼的客戶端。將全部參數信息組織成一個總體對象,而後轉換成json對象,設置爲post請求content的值,提交到服務端。此時服務端接口方法獲取參數即須要採用本文討論的方式。其實本文method1方法也能夠自定義一個包含p1和p2兩個字段的JavaBean類型,本身能夠嘗試一下,呵呵! mvc