首先请求头需要有:Content-type: application/json

当然,这句话是告诉服务器,请求体中 requestBody 是JSON对象序列化后的值。


在很多时候,我们需要像服务器提交的数据,在服务端并没有对应的javaBean。所以我们无法将他们封装到某个实体类中,但是如果一个个参数赋值,又会让代码变得比较冗余(如果参数较多),这时你就在想,要是能给我们提交的对象封装成map多好。要谁取谁。我也看了很多篇博客,写的都是皮毛。没有直击精髓。当然,你也可以抱着这样的心态看这篇文章。

场景

   如果你的需求是这样,提交如下 json 数据,

  {
    "table": "avtivity_advanced",
    "order": "time",
    "transit": {
        "time": 1597407840218,
        "sign": "2c9e49aedb0c1fb5c67ee8a93f13bb59"
    }
}

你希望 spring mvc 在后端将该 json对象封装成map<String,Object>,而对于 transit 又是一个子map对象。


解决

   @PostMapping("/updJson")
    public String updJson(@RequestBody Map<String,Object> data) throws JsonProcessingException {
        System.out.println(data);
        LinkedHashMap map = (LinkedHashMap) data.get("transit");
        System.out.println(map.get("time"));
        return "success";
    }

解析:

    其中 @RequestBody 是表明参数来源于请求体,因为我是post请求,所以数据在请求体中,如果你是 get 请求,那么使用 @RequestParam  

    通过实践发现,spring mvc会将传上来的数据封装成 LinkedHashMap ,该类是继承 HashMap,同样可以 获取 key-value,但是比HashMap多的是他会具有顺序,我们知道 HashMap是无序的,而 LinkedHashMap是有序的。


    那么很显然,上面代码中,data ,data.get("time") 都是 LinkedHashMap。但是因为 我封装时指定 map<String,Object>,所以需要强转一下。

    如果当 数据中具有 Array时。也就是下面这种情况

  {
    "table": "avtivity_advanced",
    "order": "time",
    "transit": {
        "time": 1597407840218,
        "sign": "2c9e49aedb0c1fb5c67ee8a93f13bb59"
    },
    "array":[1,2,3,4,5,6]
}

这时 我们需要,并且想把 array 解析并封装成 ArrayList ,其实spring mvc已经帮我们做好了,我们只需要强转一下就好了;


代码就会变成:

 @PostMapping("/updJson")
    public String updJson(@RequestBody Map<String,Object> data) throws JsonProcessingException {
        System.out.println(data);
        ArrayList array= (ArrayList) data.get("array");
        System.out.println(array);
        return "success";
    }


总结

我们上面分析可以知道,在 json 对象传输时,spring mvc非常智能的帮我们把 json 的 object 转变成 linkedHashMap,将json的array转变成 ArrayList。

object -> linkedHashMap

array   ->ArrayList


严格来说,array也是属于 object,但是此 object非彼object。这样一来,两个转化 解决了我们大部分场景需求,要知道 spring mvc如此强大,这些工程师们肯定比我们这些小垃圾考虑的周全。



提醒

对于请求中,文章开头的键值对不要忘记,放到 headers 中。而 在 post 请求中,一定要将json对象使用 JSON.stringify() 序列化后的值。下面给出一段原生的ajax请求的样例。为什么是原生,因为懒得引入jq。

function ajaxPost(url, data, callback) {
  var xhr = new XMLHttpRequest();
  xhr.open('POST', url, true);
  xhr.setRequestHeader('Content-type', 'application/json');
  xhr.send(data);

  xhr.onreadystatechange = function () {
    if (xhr.readyState == 4 && xhr.status == 200) {
      callback(xhr.responseText);
    }
  }
}

// 调用
ajaxPost('/updJson', JSON.stringify({
    "table": "avtivity_advanced",
    "order": "time",
    "transit": {
        "time": 1597407840218,
        "sign": "2c9e49aedb0c1fb5c67ee8a93f13bb59"
    }
}), function (data) {
  // 后台返回的数据就是 字符串类型。要转成json,必须自己手动转换。

  console.log(data);

});

你可以直接在对应的域名下控制台输入这段代码以作测试。就像下面这样。

sprin mvc传入JSON数据,序列化为Map对象(图1)