前言
HTTP 协议是以 ASCII 码传输,建立在 TCP/IP 协议之上的应用层规范。规范把 HTTP 请求分为三个部分:状态行、请求头、消息主体。类似于下面这样:
<method> <request-URL> <version>
<headers>
<entity-body>
协议规定 POST 提交的数据必须放在消息主体(entity-body)中,但协议并没有规定数据必须使用什么编码方式。实际上,开发者完全可以自己决定消息主体的格式,只要最后发送的 HTTP 请求满足上面的格式就可以。
但是,数据发送出去,还要服务端解析成功才有意义。一般服务端语言如 php、python ,java等,以及它们的 framework,都内置了自动解析常见数据格式的功能。服务端通常是根据请求头(headers)中的 Content-Type 字段来获知请求中的消息主体是用何种方式编码,再对主体进行解析。post提交数据有四种方式,下面介绍他们以及前端应该如何传参
Content-Type请求头指定了发送给服务器的数据类型,这决定了data字段的格式。以下是几种常见的Content-Type值及其对应的data格式:
1. application/x-www-form-urlencoded
当Content-Type设置为此值时,data应该是一个URL编码的查询字符串,通常由qs.stringify或类似方法生成。
qs可以将json序列化如下:
let a = {
name:'june',
age:26
}
qs.stringify(a) //"name=june&age=26" qs可以将josn对象转换成形如key&value
如何使用:
import qs from 'qs'
let data = {code: 'fds', headImgUrl: '99', innerDemoVos: [{code: '篮球', name: 'xx'}, {code: '台球', name: '小芳'}]}
let params = qs.stringify(data, {arrayFormat: 'indices', allowDots: true})
// post的content-type的格式需要设置成application/x-www-form-urlencoded,data就是post请求体。
let data = {code: 'fds', headImgUrl: '99', innerDemoVos: [{code: '篮球', name: 'xx'}, {code: '台球', name: '小芳'}]};
// 将json对象转换成form表单的key&value的形式,包括复杂的数组对象,注意{arrayFormat: 'indices', allowDots: true}参数,一定要写,这个关系到数组对象转换成的格式后台是否可以解析,如果不写那么数组对象就是innerDemo[0].[code]: 篮球,这样后台是无法解析,只有innerDemo[0].code: 篮球的格式才可以解析,
console.info(qs.stringify(data, {arrayFormat: 'indices', allowDots: true}));
这是默认的编码方式,表单数据会被编码为键值对形式,通常用于提交表单。在这种方式下,参数以键值对的形式出现在请求体中,键和值之间使用"="连接,而不同的键值对之间使用"&"分隔。这种方式适合传输简单的键值对数据。
2. application/json
当Content-Type设置为application/json时,data应该是一个JSON字符串,可以通过JSON.stringify方法转换一个JavaScript对象来得到。
let param = {
name : 'xiaohong',
age: 18,
sex: '女',
goods: {
a: 1,
b:2
}
}
传参直接传json对象param,非常简单
当需要传输复杂的数据结构时,如对象或数组,通常会使用JSON格式。JSON数据是一种轻量级的数据交换格式,易于阅读和编写,同时也易于机器解析和生成。在HTTP请求中,JSON数据作为请求体发送,服务器端可以通过解析JSON数据来获取请求的具体内容。
3. multipart/form-data
这个Content-Type通常用于上传文件,此时data应该是一个FormData对象,可以使用new FormData()创建,并通过append方法添加键值对或文件。
const formData = new FormData();
// 添加键值对
formData.append('username', 'john_doe');
formData.append('password', 'secret');
// 添加文件
const fileInput = document.getElementById('file-input');
const file = fileInput.files[0];
if (file) {
formData.append('avatar', file, file.name);
}
// 发送请求
const response = await fetch('/api/upload', {
method: 'POST',
body: formData
});
// 处理响应
const data = await response.json();
console.log(data);
这种编码方式适合上传文件等需要分割的数据。它可以将表单数据编码为一条一条的消息,每一条消息都可以有自己的头部信息,允许同时上传多个文件或表单数据。
4.text/plain
这种方式适合传输纯文本数据,数据以纯文本形式出现在请求体中,不进行任何编码或格式化。
因此,根据Content-Type的不同,data的格式会有所变化,以适应不同的请求需求。
get方式和post方式的区别:
get方式没有http-body。参数在url中key=value形式传递。对值进行URLencode编码。
post方式和get方式对立。包含http-body。把数据放到http-body中。
根据以上的描述,可以总结:
get方式的请求:Content-Type只能为application/x-www-form-urlencoded。没有别的选择。
post方式的请求:Content-Type可以选择application/x-www-form-urlencoded , multipart/form-data , application/json,三种方式。
在vue中Axios传参json可以不需要JSON.stingify对data进行转换
在现代Web开发中,尤其是使用诸如Axios、Fetch API等较新的HTTP客户端库时,有时候我们不再显式地使用 JSON.stringify() 来序列化对象,这是因为这些库内部已经处理了数据序列化的问题。以下是一些原因:
- 自动序列化: 现代的HTTP客户端库如Axios和Fetch
API能够自动识别Content-Type并相应地序列化数据。当你设置Content-Type为application/json时,它们会自动调用JSON.stringify()来转换JavaScript对象为JSON字符串。 - 更简洁的代码:
直接传递JavaScript对象作为请求体参数,而不是先调用JSON.stringify(),可以使代码更加简洁和易于阅读。 - 减少错误: 自动序列化减少了手动序列化可能引入的错误,比如忘记调用JSON.stringify()或序列化失败导致的错误。
- 统一的接口: 现代库提供了更统一的接口,使得无论是GET还是POST请求,数据的处理方式都更加一致,不需要关心底层的细节。
然而,这并不意味着JSON.stringify()已经过时或完全不需要了。在某些情况下,你仍然需要使用它,例如:
当你直接操作XMLHttpRequest或使用不支持自动序列化的旧库时。
当你需要手动控制序列化过程,例如使用replacer或space参数时。
当你正在编写与JSON数据交互的通用工具函数或库时。
总的来说,是否使用JSON.stringify()取决于你使用的具体库或框架以及你对数据序列化的需求。在大多数现代Web开发项目中,你可能不需要频繁地直接调用JSON.stringify(),而是依赖于更高层次的抽象来处理这些细节。