写点什么

重学 JS | Ajax 发送数据序列化问题以及 Object 序列化整理

用户头像
梁龙先森
关注
发布于: 2021 年 01 月 26 日
重学JS | Ajax发送数据序列化问题以及Object序列化整理

问题

前端 ajax 请求发送数组,后端接口接到到为 null,这问题应该很经常碰到,这里来重温下。

前端 Ajax 请求:


let data = { ids:[1,2,3,4]}// 普通的post,只不过里面是ids数组$.ajax({ type:"POST", url:"user/saveUser", dataType:"json", contentType:"application/json", data:data, success:function(data){ } });
复制代码

后端接口定义:


public
复制代码

理想认为接口可以接收成功,但实际上并没有。

原因

这是因为,ajax 请求默认对参数进行了深度序列化,然而 servelt api 无法处理这个,这也就导致了接口接收到的为 null。深度序列化后接口参数为:ids[]=1&ids[]=2&ids[]=3,通过 ids 自然就获取不到了。

解决办法

解决这个问题的方法有如下:

  1. 通过给 ajax 请求设置:traditional:true,使用传统的方式浅层序列化(参数序列化),此时传递的数据参数为:ids=1&ids=2&ids=3 。接口无需修改,可直接获取参数。

  2. 将传递的数组转为字符串,通过字符串进行传输。{ids:JSON.stringify([1,2,3])},此时后端接口需要做相应的调整。

知识扩展

JSON 序列化

JSON 序列化是将 JSON 对象处理为 JSON 字符串的过程,以方便数据传输。可以通过JSON.stringify()或者对象自定义toJSON()函数来实现。

  1. JSON.stringify()函数

用法如下:

// object:要序列化的对象// replacer:可选参数,若为函数,表示序列化过程中,被序列化的每个值都会经过该函数处理。//          若为数组,则表示只有存在数组中的属性,才参与序列化。// space:可选参数,指定缩进的空白字符串,美化输出。最小值是1,上限值是10.JSON.stringify(object,replacer,space)
复制代码

举个例子:

var obj = {	name:'zhangsan',  age:12,  hobits:['ball','games']}
// 1. 自定义个函数var replacer = function(key,value){ if(typeof value==='string'){ // 将字符转为大写 return value.toUpperCase() } return value}//输出: {name:'ZHANGSAN',age:12,hobits:['BALL','GAMES']}JSON.stringify(object,replacer)
// 2. 自定义数组var replacer = ['name']// 输出:"{"name":"zhangsan"}"JSON.stringify(object,replacer)
复制代码

为什么数组也转换成大写字母了呢?

JSON 序列化时,如果属性为对象或者数组,则会继续序列化该属性值,直到属性值为基本类型、函数或者 Symbol 类型才结束。


  1. 自定义 toJSON()函数

如果被序列化的对象拥有 toJSON()函数,那么 toJSON()函数会覆盖默认的序列化行为,被序列化的值将变成是 toJSON()函数的返回值。它可以更精确的控制序列化,可以理解为是对 stringify 函数的补充。

var object = {	name:'张三',  age:12,  city:'北京',  toJSON:function(){ // 这里不能使用箭头函数,因为执行object.toJSON()将继承父作用域,this不指向object  	return {    	Name:this.name,      Age:this.age    }  }}JSON.stringify({name:object},['name'])// 输出的是:"{"name":{}}"
复制代码
  1. object.toJSON()后返回的是{"Name":"张三","Age":12},此时序列化变化{"name":{"Name":"张三","Age":12}}

  2. 第二个参数 replacer 是数组["name"],此时过滤的是 name 属性,但 name 属性是个对象,因此对对象的属性进行递归序列化,而这里的属性不存在 name,所以过滤 后就为一个空对象{}。

JSON 反序列化

JSON 反序列就是将 JSON 字符串转换为 JSON 对象的过程,这里存在两种方式,一种是通过 JSON.parse()函数,另一种是通过 eval()。

  1. JSON.parse()

基本用法如下:

// text: 接收的json字符串// reviver: 可选参数,若为函数,则规定了原始值在返回之前如何被解析改造。JSON.parse(text,reviver)
复制代码

例子如下:

var text = "{"name":"zhangsan","age":12,"hobits":["ball","games"]}"JSON.parse(text,function(key,value){	if(key==='name'){  	return value+'同学'  }  return value})// 输出:{	name:'zhangsan同学',  age:12,  hobits:['ball','games']}
复制代码


  1. eval()函数

eval()函数用于计算 JavaScript 字符串,并把它当作脚本来执行。

var text = '{"name":"zhangsan","age":12,"hobits":["ball","games"]}'var object = eval("("+text+")")// 输出:{	name:'zhangsan',  age:12,  hobits:['ball','games']}
复制代码

总结

至此我们学习了序列化与反序列化。

发布于: 2021 年 01 月 26 日阅读数: 14
用户头像

梁龙先森

关注

脚踏V8引擎的无情写作机器 2018.03.17 加入

还未添加个人简介

评论

发布
暂无评论
重学JS | Ajax发送数据序列化问题以及Object序列化整理