一、前言
在 JavaScript 开发中,JSON.parse() 和 JSON.stringify() 是使用率极高的一对核心方法,主要用于 JSON 字符串与 JS 对象的相互转换。
绝大多数开发者只会基础用法,却不了解深层参数、转换规则、特殊数据丢失、循环引用报错、序列化异常等高频坑点。
本文从零拆解两个方法的基础语法、完整参数、实战场景、核心区别、全网高频避坑点,一篇彻底吃透,适配日常开发、面试手撕、数据处理全场景。
二、核心本质一句话区分
- JSON.stringify() :序列化,JS 对象/数组 → JSON 字符串(输出字符串)
- JSON.parse() :反序列化,JSON 字符串 → JS 对象/数组(还原对象)
简单记忆:stringify 转字符串,parse 解字符串。
三、JSON.stringify() 超全详解(序列化)
1、基础作用
将 JavaScript 引用类型数据(对象、数组)转换为 标准 JSON 格式字符串,常用于数据存储、本地缓存、接口传参、深拷贝等场景。
2、基础语法
javascript
JSON.stringify(value, replacer, space)
参数说明:
- value(必传) :需要序列化的 JS 对象、数组、基础数据
- replacer(可选) :过滤/转换函数或数组,用于筛选、修改序列化字段
- space(可选) :缩进空格数,用于格式化输出 JSON 字符串
3、基础用法示例
javascript
const obj = { name: '前端开发', age: 20, hobby: 'coding' }
// 对象转 JSON 字符串
const jsonStr = JSON.stringify(obj)
console.log(jsonStr)
// 输出:{"name":"前端开发","age":20,"hobby":"coding"}
console.log(typeof jsonStr) // string
4、高阶参数实战用法
4.1 第二个参数:数组过滤指定字段
只序列化数组中配置的字段,其余字段直接过滤丢弃。
javascript
const obj = { name: '前端开发', age: 20, hobby: 'coding' }
// 仅保留 name、age 字段
const jsonStr = JSON.stringify(obj, ['name', 'age'])
console.log(jsonStr)
// 输出:{"name":"前端开发","age":20}
4.2 第二个参数:函数自定义处理字段
可对序列化的 键值对 做自定义拦截、修改、重置逻辑。
javascript
const obj = { name: '前端开发', age: 20, hobby: 'coding' }
const jsonStr = JSON.stringify(obj, (key, value) => {
// 对age字段单独处理
if (key === 'age') return 99
return value
})
console.log(jsonStr)
// 输出:{"name":"前端开发","age":99,"hobby":"coding"}
4.3 第三个参数:格式化缩进输出
默认压缩输出,设置数值(1-10)可自动缩进格式化,方便日志查看。
javascript
const obj = { name: '前端开发', age: 20 }
const jsonStr = JSON.stringify(obj, null, 2)
console.log(jsonStr)
// 格式化缩进输出
四、JSON.parse() 超全详解(反序列化)
1、基础作用
将标准 JSON 格式字符串,还原为 原生 JS 对象/数组,是序列化的反向操作,常用于后端数据解析、本地缓存数据读取。
2、基础语法
arduino
JSON.parse(text, reviver)
参数说明:
- text(必传) :标准合法的 JSON 字符串
- reviver(可选) :回调函数,用于解析时二次处理键值对数据
3、基础用法示例
javascript
const jsonStr = '{"name":"前端开发","age":20}'
// 字符串转 JS 对象
const obj = JSON.parse(jsonStr)
console.log(obj) // { name: '前端开发', age: 20 }
console.log(typeof obj) // object
4、高阶参数:reviver 数据二次处理
解析过程中可对指定字段做类型转换、数值修改、数据过滤。
javascript
const jsonStr = '{"name":"前端开发","age":20}'
const obj = JSON.parse(jsonStr, (key, value) => {
// 将age转为字符串
if (key === 'age') return String(value)
return value
})
console.log(obj.age, typeof obj.age) // '20' string
五、开发高频实战场景(必用)
1、localStorage 本地缓存数据
本地存储只能存字符串,对象/数组必须先序列化,读取后反序列化还原。
javascript
const user = { name: 'test', id: 1001 }
// 存储:对象转字符串
localStorage.setItem('user', JSON.stringify(user))
// 读取:字符串转对象
const userInfo = JSON.parse(localStorage.getItem('user'))
2、简单深拷贝(经典面试题)
通过序列化+反序列化,快速实现对象/数组深拷贝,零依赖、写法极简。
javascript
const originObj = { name: '前端', info: { age: 20 } }
// 深拷贝核心写法
const newObj = JSON.parse(JSON.stringify(originObj))
3、接口参数格式化、数据过滤
通过 stringify 第二个参数过滤无效字段、空字段,精简接口传参。
4、Vue3 专属高频实战案例(项目必用)
在 Vue3 + Vite 项目中,JSON 的序列化与反序列化是本地持久化、组件复杂传参、响应式数据处理的核心操作,下面分享 4 个可直接复制上线的高频实战案例。
案例1:Vue3 本地持久化响应式用户数据
Vue3 项目中常用 Pinia / localStorage 存储用户信息,对象类型数据必须通过 JSON 方法转换,否则会出现数据存储失效、读取异常问题。
xml
<script setup>
import { ref } from 'vue'
// 定义响应式用户数据
const userInfo = ref({
name: '前端开发者',
age: 22,
token: 'xxxxxxx'
})
// 数据持久化:序列化存储
const saveUserInfo = () => {
localStorage.setItem('userInfo', JSON.stringify(userInfo.value))
}
// 页面初始化读取:反序列化还原
const getUserInfo = () => {
const str = localStorage.getItem('userInfo')
if (str) {
userInfo.value = JSON.parse(str)
}
}
// 页面加载读取数据
getUserInfo()
</script>
案例2:Vue3 父子组件复杂对象传参
Vue3 组件传参基础类型可直接传递,复杂对象、数组、多层嵌套数据可通过 JSON 序列化传参,规避响应式失效、数据双向污染问题。
父组件 Father.vue
xml
<template>
<!-- 序列化后传递字符串,避免子组件篡改父组件原始数据 -->
<Child :list="JSON.stringify(tableList)" />
</template>
<script setup>
import Child from './Child.vue'
import { ref } from 'vue'
// 复杂嵌套数组数据
const tableList = ref([
{ id: 1, title: 'Vue3实战', status: 1 },
{ id: 2, title: 'JSON解析', status: 0 }
])
</script>
子组件 Child.vue
xml
<script setup>
import { defineProps } from 'vue'
// 接收字符串,解析还原为数组
const props = defineProps(['list'])
const list = JSON.parse(props.list)
console.log(list) // 正常获取数组数据
</script>
案例3:Vue3 路由复杂参数传参(解决params丢失)
Vue3 路由 params 传参刷新页面丢失 ,可通过 JSON.stringify 序列化后放入 query 传递,实现刷新不丢失,完美解决路由传参痛点。
xml
<script setup>
import { useRouter } from 'vue-router'
const router = useRouter()
// 复杂对象参数
const detailData = { id: 1001, name: '详情数据', list: [1,2,3] }
// 跳转页面,序列化复杂对象存入query
const goDetail = () => {
router.push({
path: '/detail',
query: {
info: JSON.stringify(detailData)
}
})
}
</script>
目标页面接收解析:
xml
<script setup>
import { useRoute } from 'vue-router'
const route = useRoute()
// 解析还原复杂对象,刷新页面不丢失数据
const info = JSON.parse(route.query.info)
console.log(info)
</script>
案例4:Vue3 表单数据格式化提交(过滤空值)
借助 JSON.stringify 第二个参数,自动过滤表单空字段、无效字段,精简请求参数,适配后端接口参数校验规则。
xml
<script setup>
import { ref } from 'vue'
import axios from 'axios'
// 表单数据
const form = ref({
name: 'Vue3',
age: '',
desc: '前端实战',
type: null
})
// 过滤空值、null值字段
const submitForm = async () => {
const params = JSON.parse(JSON.stringify(form.value, (key, val) => {
// 过滤空字符串、null、undefined
if (val === '' || val === null || val === undefined) return undefined
return val
}))
// 接口提交精简后的数据
await axios.post('/api/submit', params)
}
</script>
Vue3 使用核心注意点
- 响应式数据转换 :处理 ref/reactive 响应式数据时,必须取
.value原值再序列化,否则会打包响应式代理标识,数据异常 - 防止数据污染:组件传参序列化传递字符串,可切断引用关系,杜绝子组件篡改父组件原始数据
- 路由参数兼容:复杂对象路由传参优先序列化存入 query,彻底解决 params 刷新丢失问题
- 表单优化:利用高阶参数自动过滤无效参数,减少后端参数报错,精简请求体积
六、核心转换规则(避坑基础)
很多数据异常、丢失问题,都源于不了解 JSON 序列化规则:
- undefined、函数、Symbol:序列化时直接丢失、忽略
- NaN、Infinity、-Infinity :序列化后变为 null
- Date 对象:序列化后转为 ISO 时间字符串,不再是 Date 对象
- 正则、Error 对象 :序列化后变为空对象
{} - 循环引用对象 :直接报错
TypeError - 键名单引号、换行、特殊格式:非标准 JSON 字符串,parse 直接报错
七、全网高频坑点与解决方案(重点)
坑点1:深拷贝丢失特殊数据
通过 JSON 深拷贝时,undefined、函数、正则等数据会丢失,复杂对象不建议使用该方式深拷贝。
坑点2:parse 解析报错
报错原因:JSON 字符串不标准(键名单引号、尾部逗号、换行、特殊字符)
解决方案:使用 try-catch 包裹,防止页面崩溃
javascript
function safeParse(str) {
try {
return JSON.parse(str)
} catch (err) {
return null
}
}
坑点3:循环引用序列化报错
ini
const obj = {}
obj.self = obj
// 报错:Converting circular structure to JSON
JSON.stringify(obj)
解决:自定义过滤函数,剔除循环引用字段。
坑点4:null、undefined 转换差异
undefined 在对象中会被忽略,单独序列化会返回 undefined;null 可正常序列化保留。
八、二者核心区别总结(面试必背)
| 方法 | 作用 | 转换方向 | 核心用途 |
|---|---|---|---|
| JSON.stringify() | 序列化 | JS数据 → JSON字符串 | 数据存储、缓存、传参、格式化 |
| JSON.parse() | 反序列化 | JSON字符串 → JS数据 | 解析后端数据、读取缓存数据 |
九、最终总结
1、JSON.stringify:对象转字符串,支持字段过滤、格式化输出,常用于数据存储传输;
2、JSON.parse:字符串还原对象,支持解析后数据二次处理,常用于数据解析;
3、JSON 转换存在严格数据规则,特殊数据会丢失、异常,需规避循环引用、非标准字符串等坑点;
4、简单深拷贝、本地缓存、接口传参是日常开发最高频的使用场景。