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

这是我参与更文挑战的第23天,活动详情查看:更文挑战

[重学JavaScript系列文章连载中…]

问题

前端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']
}
复制代码

总结

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

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享