JavaScript中Date类型数据发送前的序列化位置与自定义格式化问题
问题解析与解决方案
为什么Date会被转成ISO格式字符串?
当你通过fetch、XMLHttpRequest或Axios等工具发送JSON格式请求时,最终都会调用JSON.stringify()来序列化JavaScript对象。由于JSON规范本身没有定义Date类型,JSON.stringify()会自动调用Date对象的toISOString()方法,将其转换为YYYY-MM-DDTHH:mm:ss.sssZ格式的字符串——这就是你看到的结果的来源,整个转换过程发生在请求数据序列化阶段。
不修改字段类型的解决方案
1. 自定义JSON.stringify的replacer函数
这是最灵活的方案,只针对当前请求的Date字段做格式化,不影响全局:
// 示例数据 const payload = { eventDate: new Date('2022-12-29'), otherField: 'some value' }; // 序列化时自定义Date格式 const serializedData = JSON.stringify(payload, (key, value) => { if (value instanceof Date) { // 转换为dd-mm-yyyy格式 const day = String(value.getDate()).padStart(2, '0'); const month = String(value.getMonth() + 1).padStart(2, '0'); const year = value.getFullYear(); return `${day}-${month}-${year}`; } return value; }); // 发送请求 fetch('/your-api-endpoint', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: serializedData });
2. 全局重写Date.prototype.toJSON
如果你的项目中所有Date对象都需要统一用指定格式序列化,可以全局修改toJSON方法(注意:会影响所有使用JSON.stringify()的场景,需谨慎):
// 重写Date的toJSON方法 Date.prototype.toJSON = function() { const day = String(this.getDate()).padStart(2, '0'); const month = String(this.getMonth() + 1).padStart(2, '0'); const year = this.getFullYear(); return `${day}-${month}-${year}`; }; // 后续所有JSON序列化都会自动使用该格式 const payload = { eventDate: new Date('2022-12-29') }; console.log(JSON.stringify(payload)); // 输出 {"eventDate":"29-12-2022"}
3. 使用请求拦截器(适用于Axios等库)
如果用Axios发送请求,可以通过拦截器统一处理所有请求的Date字段,避免重复代码:
// 添加请求拦截器 axios.interceptors.request.use(config => { if (config.data) { // 序列化时处理Date字段 config.data = JSON.stringify(config.data, (key, value) => { if (value instanceof Date) { const day = String(value.getDate()).padStart(2, '0'); const month = String(value.getMonth() + 1).padStart(2, '0'); const year = value.getFullYear(); return `${day}-${month}-${year}`; } return value; }); } return config; }); // 发送请求时无需额外处理 axios.post('/your-api-endpoint', { eventDate: new Date('2022-12-29') });
内容的提问来源于stack exchange,提问作者DucLV
相关产品推荐
相关产品推荐

