最合适的Ajax内容编码类型
原文地址:我的博客
背景
在公司开发的一个页面的Ajax请求使用了contentType:application/json
,被后台的同事要求用x-www-form-urlencoded
,撕逼撕不过他,赶紧回来学学知识。
引入
contentType
是指http/https发送信息至服务器时的内容编码类型,contentType
用于表明发送数据流的类型,服务器根据编码类型使用特定的解析方式,获取数据流中的数据。内容编码类型的作用,有点像本地文件的后缀名。
问题来了
发送Ajax请求最合适的内容编码类型是什么?
常见的contentType
x-www-form-urlencoded
这是Jquery/Zepto Ajax默认的提交类型。最简例子为:
let userInfo = { name: 'CntChen',info: 'Front-End',} $.ajax({ url: 'https://github.com',type: 'POST',data: userInfo,success: (data) => {},});
此时默认的提交的contentType
为application/x-www-form-urlencoded
,此时提交的数据将会格式化成:
name=CntChen&info=Front-End
HTML的form
表单默认的提交编码类型也是x-www-form-urlencoded
,可能这就是Jquery/Zepto等类库(其实是Ajax:XMLHttpRequest)也默认使用contentType:x-www-form-urlencoded
的原因,毕竟表单的历史比Ajax早多了。--我猜的,待验证
如果请求类型type
是GET
,格式化的字符串将直接拼接在url后发送到服务端;如果请求类型是POST
,格式化的字符串将放在http body的Form Data中发送。
json
使用json内容编码发送数据,最简例子为:
let userInfo = { name: 'CntChen',Info: 'Front-End',contentType: 'application/json',data: JSON.stringify(userInfo),});
最主要的不同有3点:
需要显式指定
contentType
为application/json
,覆盖默认的contentType需要使用
JSON.stringify
序列化需要提交的数据对象,序列化的结果为:
{"name":"CntChen","info":"Front-End"}
提交的类型不能为
GET
,使用GET
的话,数据会在url中发送,此时就无法以json字符串的编码发送
multipart/form-data
When you are writing client-side code,all you need to know is use multipart/form-data when your form includes any < input type="file" > elements.
multipart/form-data
主要用于传输文件数据的。
JS对象编码
对于扁平的参数对象,使用x-www-form-urlencoded
或json
并没有大的差别,后台都可以处理成对象,并且数据编码后的长度差别不大。
但是对于对象中嵌套对象,或对象字段包含数组,此时两种内容编码方式就有较大差别。
对象嵌套
{ userInfo :{ name: 'CntChen',login: true,},}
to x-www-form-urlencoded
(1)
userInfo[name]=CntChen&userInfo[info]=Front-End&userInfo[login]=true
to json
(2)
{"userInfo":{"name":"CntChen","Info":"Front-End","login":true}}
对象字段为数组
{ authors:[ { name: 'CntChen',{ name: 'Eva',info: 'Banker',} ],}
to x-www-form-urlencoded
(3)
authors[0][name]=CntChen&authors[0][info]=Front-End&authors[1][name]=Eva&authors[1][info]=Banker
to json
(4)
{"authors":[{"name":"CntChen","info":"Front-End"},{"name":"Eva","info":"Banker"}]}
可见:x-www-form-urlencoded
是先将对象铺平,然后使用key=value
的方式,用&
作为间隔。对于嵌套对象的每个字段,都要传输其前缀,如(1)
中的userInfo
重复传输了3次;(3)
中authors传输了4次。
如果对象是多重嵌套的,或者嵌套对象的字段较多,x-www-form-urlencoded
会产生更多冗余信息。同时,x-www-form-urlencoded
可读性不如json
字符串。
回答问题:json最好
较小的传输量
从前文可以看出,使用json字符串的形式,可以减少冗余字段的传输,减少请求的数据量。
补充:可能你会觉得
(4)
中数组内的name
和info
也传输了多次,是不是也存在冗余?其实这不是冗余。因为对数组中的各对象,并不要求其具有相同的字段(数组中的对象并不是结构化的),所以不能忽略“相同”的字段名。使用x-www-form-urlencoded
编码方式,数组内对象的字段也是重复传输。
请求与返回统一
目前许多前后端交互的返回数据是json字符串,这可能是考虑较小的传输量而作出的选择。同时,ES3.1添加了JSON对象,许多浏览器可以直接使用JSON对象,可以将json字符串解析为JS对象(JSON.parse
),将JS对象编码为json字符串(JSON.stringify
);
所以使用json编码请求数据,其编码解码非常方便,并且可以保持与后台返回数据的格式一致。
一致是一件很美好的事情。
框架的支持
目前Mvvm的前端框架如React,网络请求通常是提交一个JS对象(传输的时候编码为json字符串)。后台服务器如Koa,接收请求和响应的数据是json字符串。
可读性高
可读性高是json格式自带buff。
结论
赶紧使用contentType=applications/json
。
References
Ajax
x-www-form-urlencoded VS json - Pros and Cons. And Vulns.
What does enctype='multipart/form-data' mean?
Can I use JSON
JSON