开发者社区> 问答> 正文

springmvc中如何获取POST提交的JSON字符串??报错

Hi,

    我们知道可以在Controller中使用@RequestBody 注解自动装配对象获得前台POST过来的JSON字符串,但是现在我想直接获取一个json字符串应该如何获取?

    如:有JSON字符串{"code":"abc"}  我想直接获取code的值但是不装配成对象该怎么办?

    Controller代码如下:

@RequestMapping(value = "/isExistByCode", method = RequestMethod.POST)
    public boolean isExistByCode(@RequestBody String code) {
        return abilityService.isExistByCode(code);
    }



    使用如下单元测试方法报错


@Test
    public void testIsExistByCode() throws Exception
    {
        String jsonStr = "{\"code\":\"465\"}";
        mockMvc.perform(post("/ability/isExistByCode").contentType(MediaType.APPLICATION_JSON).content(jsonStr)).andExpect(status().isOk()).andDo(print());
    }


异常信息:
15,130 [main] INFO  c.n.core.log.LogExceptionHandler - requestBody={"code":"aaa465"}
2014-07-23 21:12:15,135 [main] ERROR c.n.core.log.LogExceptionHandler - exception trace
org.springframework.http.converter.HttpMessageNotReadableException: Could not read JSON: Can not deserialize instance of java.lang.String out of START_OBJECT token




   

展开
收起
爱吃鱼的程序员 2020-06-15 19:50:47 1119 0
1 条回答
写回答
取消 提交回答
  • https://developer.aliyun.com/profile/5yerqm5bn5yqg?spm=a2c6h.12873639.0.0.6eae304abcjaIB

    1.如上面一哥们说的,但是不建议使用


    method(@RequestBodyMapmap){map.get("code");}


    2.直接将requestcontent转换为JSONObject(配置Converter,springmvc会帮我们做)

    method(@RequestBodyJSONObjectjsonObj){jsonObj.getString("code");}










    自动转不了吧,还是要对象或者map,因为是JSON过来之后是LinkedHashMap回复 @puras:既然选择使用json和服务端交互,那么用JSON对象来接收数据肯定是最好的,不知道你指的复杂情况是什么情况,性能?你说的这种是简单的情况,有时一些复杂的情况,Spring的自动转换也没有办法帮我转换成我想要的东西。比如对象嵌套3层以上的时候。有啥好办法?或是建议使用的办法么?感觉这样略麻烦,不建议用map的原因是什么?如果装配成对象不如直接在@RequestBody的时候直接装配就好了

    实现方式:

    @JsonArg("$.resource")Stringcode



    步骤:

    1、自定义注解

    @Retention(RetentionPolicy.RUNTIME)@Target(ElementType.PARAMETER)public@interfaceJsonArg{publicStringvalue()default"";}



    2、实现  HandlerMethodArgumentResolver 

    publicclassJsonArgumentResolverimplementsHandlerMethodArgumentResolver{privatestaticfinalStringJSONBODYATTRIBUTE="JSON_REQUEST_BODY";@OverridepublicbooleansupportsParameter(MethodParameterparameter){returnparameter.hasParameterAnnotation(JsonArg.class);}@OverridepublicObjectresolveArgument(MethodParameterparameter,ModelAndViewContainermavContainer,NativeWebRequestwebRequest,WebDataBinderFactorybinderFactory)throwsException{Stringbody=getRequestBody(webRequest);Stringarg=parameter.getParameterAnnotation(JsonArg.class).value();if(StringUtils.isEmpty(arg)){arg=parameter.getParameterName();}Objectval=JsonPath.parse(body).read(arg,parameter.getParameterType());returnval;}privateStringgetRequestBody(NativeWebRequestwebRequest){HttpServletRequestservletRequest=webRequest.getNativeRequest(HttpServletRequest.class);StringjsonBody=(String)webRequest.getAttribute(JSONBODYATTRIBUTE,NativeWebRequest.SCOPE_REQUEST);if(jsonBody==null){try{jsonBody=IOUtils.toString(servletRequest.getInputStream());webRequest.setAttribute(JSONBODYATTRIBUTE,jsonBody,NativeWebRequest.SCOPE_REQUEST);}catch(IOExceptione){thrownewRuntimeException(e);}}returnjsonBody;}}



    3、spring-mvc中声明:

    <mvc:annotation-driven><mvc:argument-resolvers><beans:beanclass="com.redcollar.bl.commons.extension.JsonArgumentResolver"/></mvc:argument-resolvers></mvc:annotation-driven>







    回复 @徐建兴:com.jayway.jsonpath.JsonPath和jacksonhttp://stackoverflow.com/questions/12893566/passing-multple-variables-in-requestbody-to-a-spring-mvc-controller-using-ajax真正的大神!

    @RequestParam(value="code")Stringcode

    即可获取到

    绝逼获取不到这样获取不到吧IOUtils.toString(request.getInputStream())
    测试单元里面code=ddfg这个参数名和后面content(jsonStr)冲突了吧
    对,那个是粘贴的时候的错误,已经修改过来了。谢谢指正。

    请求包的contentType要设置成multipart/form-data,这样Servlet容器才不会解析请求包体

    另外这个东西和Spring的multipart文件上传组件冲突

    这样的:

    @RequestMapping(value="reset_passwd.json",method=RequestMethod.POST)@ResponseBodypublicObjectresetPasswd(@RequestBodyStringrequestJson){Stringmessage=null;Map<String,Object>jsonData=StringUtils.parseJson(requestJson);Stringemployee=(String)jsonData.get("employee");//...}而发起这个请求是:

    /***使用POST模拟文件上传提交一个json对象,注意这个方法提交的数据为json对象的字符串表示而非标准文件上传请求包**@paramurl*@paramparams*@return*@throwsIOException*/publicstaticStringdoJson(Stringurl,Objectdata)throwsIOException{HttpURLConnectionconnection=(HttpURLConnection)newURL(url).openConnection();connection.setDoOutput(true);connection.setConnectTimeout(Const.DEFAULT_HTTP_CONNECT_TIMEOUT);connection.setReadTimeout(Const.DEFAULT_HTTP_READ_TIMEOUT);connection.setUseCaches(false);connection.setRequestMethod("POST");connection.setRequestProperty("Content-Type","multipart/form-data");BufferedOutputStreamout=null;try{out=newBufferedOutputStream(connection.getOutputStream());out.write(StringUtils.toJson(data).getBytes(Const.DEFAULT_CHARSET));out.flush();}finally{if(out!=null){out.close();out=null;}}//...后面读取结果}



    回复 @逝水fox:您好,我现在需要使用这种方法上传json,同时我还要上传文件,上面您说这种方式回合MultipartFile冲突,那请问有什么好的解决方案呢?回复 @Kent_Chen:如果不用mutipart,首先是Tomcat有默认的2M的请求包大小限制,另外如果用application/json,SpringMVC的MessageConverter也会处理(这个并不只对@ResponseBody有效,对@RequestBody仍然是有效的),如果要自己String处理以便在json字符串异常的时候自己能有处理,这个是不方便的我又不上传为什么需要multipart/form-data

    method(@RequestBodyMapmap){

    map.get("code");

    }

    感谢指点,非常有用,看了下JSON被转成了LinkedHashMap只能用Map或者对象接收回复 @Kent_Chen:记得给最佳哈。谢谢,这个是可以的:)

    不是method(HttpServletRequestrequest){

    request.getParameter("code");

    }就好?

    @Kent_Chen我一直用的getParameter,是可以取到值的,确定是POST方法POST放在REQUESTBODY里的,getParameter是取不到的有兴趣的可以试一下参数过来是串,想直接用肯定还需要转换?要么自带提供的有,要么自己转可以用post 请求把json数据作为值,例如value=jsondata,这个时候用 getParameter可以取到,剩下的你想怎么转就怎么转,还有一种方法,自定义ConversionService
    2020-06-15 19:51:03
    赞同 展开评论 打赏
问答排行榜
最热
最新

相关电子书

更多
低代码开发师(初级)实战教程 立即下载
冬季实战营第三期:MySQL数据库进阶实战 立即下载
阿里巴巴DevOps 最佳实践手册 立即下载