12
回答
springmvc中如何获取POST提交的JSON字符串?
百度AI开发者大赛带你边学边开发,赢100万奖金,加群:418589053   

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




   
<无标签>
举报
Kent_Chen
发帖于4年前 12回/88K+阅
共有12个答案 最后回答: 5个月前

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


method(@RequestBody Map map) {

map.get("code");

}


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

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










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

实现方式:

@JsonArg("$.resource") String code



步骤:

1、自定义注解

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface JsonArg {

	public String value() default "";
	
}



2、实现  HandlerMethodArgumentResolver 

public class JsonArgumentResolver implements HandlerMethodArgumentResolver{

    private static final String JSONBODYATTRIBUTE = "JSON_REQUEST_BODY";
    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return parameter.hasParameterAnnotation(JsonArg.class);
    }

    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
        String body = getRequestBody(webRequest);
        String arg = parameter.getParameterAnnotation(JsonArg.class).value();
        if (StringUtils.isEmpty(arg)) {
        	arg = parameter.getParameterName();
        }
        Object val = JsonPath.parse(body).read(arg, parameter.getParameterType());
        return val;
    }

    private String getRequestBody(NativeWebRequest webRequest){
        HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class);

        String jsonBody = (String) webRequest.getAttribute(JSONBODYATTRIBUTE, NativeWebRequest.SCOPE_REQUEST);
        if (jsonBody==null){
            try {
                jsonBody = IOUtils.toString(servletRequest.getInputStream());
                webRequest.setAttribute(JSONBODYATTRIBUTE, jsonBody, NativeWebRequest.SCOPE_REQUEST);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return jsonBody;
    }

}



3、spring-mvc中声明:

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







--- 共有 2 条评论 ---
我疯癫回复 @徐建兴 : com.jayway.jsonpath.JsonPath和jackson http://stackoverflow.com/questions/12893566/passing-multple-variables-in-requestbody-to-a-spring-mvc-controller-using-ajax 2年前 回复
徐建兴真正的大神! 3年前 回复
测试单元里面code=ddfg这个参数名和后面content(jsonStr) 冲突了吧
--- 共有 1 条评论 ---
Kent_Chen对,那个是粘贴的时候的错误,已经修改过来了。谢谢指正。 4年前 回复

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

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

这样的:

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

/**
 * 使用POST模拟文件上传提交一个json对象,注意这个方法提交的数据为json对象的字符串表示而非标准文件上传请求包
 * 
 * @param url
 * @param params
 * @return
 * @throws IOException
 */
public static String doJson(String url, Object data) throws IOException {
	HttpURLConnection connection = (HttpURLConnection) new URL(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");
	BufferedOutputStream out = null;

	try {
		out = new BufferedOutputStream(connection.getOutputStream());
		out.write(StringUtils.toJson(data).getBytes(Const.DEFAULT_CHARSET));
		out.flush();
	} finally {
		if (out != null) {
			out.close();
			out = null;
		}
	}
	// ... 后面读取结果
}



--- 共有 2 条评论 ---
逝水fox回复 @Kent_Chen : 如果不用mutipart,首先是Tomcat有默认的2M的请求包大小限制,另外如果用application/json,Spring MVC的MessageConverter也会处理(这个并不只对@ResponseBody有效,对@RequestBody仍然是有效的),如果要自己String处理以便在json字符串异常的时候自己能有处理,这个是不方便的 4年前 回复
Kent_Chen我又不上传为什么需要multipart/form-data 4年前 回复

不是method(HttpServletRequest request){

request.getParameter("code");

}就好?

--- 共有 2 条评论 ---
戴的天@Kent_Chen 我一直用的getParameter,是可以取到值的,确定是POST方法 4年前 回复
Kent_ChenPOST放在REQUESTBODY里的,getParameter是取不到的有兴趣的可以试一下 4年前 回复
可以用post 请求把json数据作为值,例如value=jsondata,这个时候用 getParameter可以取到,剩下的你想怎么转就怎么转,还有一种方法,自定义ConversionService
顶部