javaScript的序列化与反序列化

render函数的基本实现

javaScript的序列化与反序列化

    • 一,js中的序列化
    • 二,序列化
    • 三,反序列化
    • 四,总结

一,js中的序列化

js中序列化就是对象转换成json格式的字符串,使用JSON对象的stringify方法,接收一个javaScript对象,返回一个json字符串。主要使用场景用于数据传输和对象全等对比。

const person = {name: "John",age: 30,test: {tips: '我叫王大锤',site: 'http://www.example.com',screen: null},city: "New York",
};JSON.stringify(person)

反序列化使用JSON对象的parse方法,接收一个json字符串。返回javaScript对象。主要使用场景,处理接口返回的数据,缓存数据处理。

JSON.parse(JSON.stringify(person))

本文主要讲述该功能的实现及序列化原理和反序列化

二,序列化

观察json数据的格式, 发现结构和javaScript的对象结构一样,只是整体都是字符串。原本的对象键都是用双引号包裹,值如果是字符串类型是也是双引号包裹,如果不是则是没有引号包裹。
在这里插入图片描述
数字和null值都没有被引号包裹。所以只有值是字符串的时候才需要被双引号包裹,其他类型直接转字符串。通过json字符串的规律,可以把对象对象变成json字符串。

class CustomJson {/*** 序列化函数* @param {object} param * @returns {string}*/stringify(param) {// 判断是否对象如果不是或不可转换成序列化字符串,抛出错误if (typeof param === 'object' && param !== null) {// 序列化回调函数const stringify = (p) => {const result = []// 分三种类型, 对象数组, 和非数组和对象或null类型// 使用栈的特性保存处理后的字符串, 也可以使用字符串拼接// 要手动拼接逗号// 字符串数据用双引号包裹再转成字符串, 其他基本类型数据直接转字符串if (Array.isArray(p)) {result.push('[')p.forEach((item, index) => {result.push(`${stringify(item)}${index !== p.length - 1 ? ',' : ''}`)})result.push(']')} else if (typeof p === 'object' && p !== null) {result.push('{')const len = Object.keys(p).lengthObject.keys(p).forEach((key, index) => {result.push(`"${key}":${stringify(p[key])}${(len - 1 !== index) ? ',' : ''}`)})result.push('}')} else {if (typeof p === 'string') {result.push(`"${p}"`)} else {result.push(`${p}`)}}// 最后将数组转换成字符串return result.join('')}return stringify(param)} else {throw new Error('param is not object')}
}

序列化验证一下

const person = {name: "John",age: 30,test: {tips: '我叫王大锤',site: 'http://www.example.com',screen: null,test: {tips: '我叫王大锤',site: 'http://www.example.com',screen: null,test: {tips: '我叫王大锤',site: 'http://www.example.com',screen: null,}}},city: "New York",list: ['1',2,3,{a: [{b: [1,2,3,4,5]}]}]
};
const test2 = ['1',2,3,{a: [{b: [1,2,3,4,5]}]}
]
const explamJSon = new CustomJson()
const testStr = explamJSon.stringify(person)
console.log('testStr 序列化测试对象', testStr)
console.log('JSON.parse 使用原生反序列化', JSON.parse(testStr))const testStr2 = explamJSon.stringify(test2)
console.log('testStr2 序列化测试对象', testStr2)
console.log('JSON.parse 使用原生反序列化', JSON.parse(testStr2))

可以正常转换成json字符串
在这里插入图片描述
为了验证格式的正确性,使用原生的JSON.parse反序列化转换成对象

const explamJSon = new CustomJson()
const testStr = explamJSon.stringify(person)console.log(testStr)console.log(JSON.parse(testStr))

在这里插入图片描述

测试结果,使用自定义序列化函数序列化的结果可以被原生的JSON.parse函数反序列化。验证成功。

三,反序列化

顾名思义反序列化与序列化的作用相反,序列化的时候我们将js对象转换成了json字符串。现在将json字符串转换成js对象。这个方法比序列化要复杂一些,序列化的时候对象本身格式是固定的。有特定的方法来处理。反序列化本身是要处理字符串,通过两分半的观察,json格式的字符串也是有规律的。每个属性之间的逗号可以作为分割符号来拆解字符串。拆解到最小颗粒度将值还原,最后返回结果。

class CustomJson {/*** 反序列化* @param {string} jsonData * @returns {object}*/parse (jsonData) {/*** 查询索引, 因为json之中使用英文逗号作为分割每一项, 使用栈先出,后进后出的特性, 获取,的坐标. 用数组存储返回* @param {string} str * @returns {array}*/const queryIdx = (str) => {const list = []let tempArr = []for (let i = 0; i < str.length; i += 1) {if (str[i] === '{' || str[i] === '[') {tempArr.push(str[i])}if (tempArr[tempArr.length - 1] === '{' && str[i] === '}') {tempArr.pop()}if (tempArr[tempArr.length - 1] === '[' && str[i] === ']') {tempArr.pop()}if (str[i] === ',' && tempArr.length === 0) {list.push(i)}}return list}/*** 还原数组, 在拿到分割坐标的基础之上, 将json字负串分解成字符串片段, 用数组存储返回* @param {string} val * @returns {array}*/const splitObject = (val) => {const s = val.slice(1, val.length - 1)const idxList = queryIdx(s)const tempArr = []let silceIdx = 0idxList.forEach(idx => {tempArr.push(s.slice(silceIdx, idx))silceIdx = idx + 1})tempArr.push(s.slice(silceIdx))return tempArr}/*** 分解字符串, 分别处理数组和对象* @param {string} str * @returns {object}*/const decomposeStr = (str) => {/*** 判断是不是一个合法的json字符串, 如果不是抛出错误*/if (jsonData[0] === '{' && jsonData[jsonData.length - 1] !== '}' || jsonData[0] === '[' && jsonData[jsonData.length - 1] !== ']') {throw new Error('jsonData is not json string')} else if (jsonData[0] != '{' || jsonData[0] === '[') {throw new Error('jsonData is not json string')}const result = str[0] === '[' ? [] : {}if (Array.isArray(result)) {const arr = splitObject(str)arr.forEach(item => {if (item.trim()[0] === '{' && item.trim()[item.trim().length - 1] === '}' || item.trim()[0] === '[' && item.trim()[item.trim().length - 1] === ']'){result.push(decomposeStr(item.trim()))} else {result.push(convertVlaue(item.trim()))}})} else {const arr = splitObject(str)arr.forEach(item => {if (item.trim()[0] === '{' && item.trim()[item.trim().length - 1] === '}' || item.trim()[0] === '[' && item.trim()[item.trim().length - 1] === ']'){result.push(decomposeStr(item.trim()))} else {const keyValues = item.trim()const divideIdx = keyValues.indexOf(':')const key = keyValues.slice(0, divideIdx)const value = keyValues.slice(divideIdx + 1)result[key.trim().slice(1, key.length - 1)] = convertVlaue(value)}})}return result}/*** 转换值, 根据之前不同的类型,将值还原, * 在序列化的时候, 因为特殊处理了字符串数据,发现是有双引号包裹的去掉双引号.* 没有双引号包裹的特殊值,特殊处理* @param {string} val * @returns {any}*/const convertVlaue = (val) => {if (val[0] === '"' && val[val.length - 1] === '"') {return val.slice(1, val.length - 1)} else if (val === 'null') {return null} else if (val === 'true') {return true} else if (val === 'false') {return false} else if (val === 'NaN') {return NaN} else if (Number(val) === 0 || Number(val)) {return Number(val)} else if (val[0] === '{' && val[val.length - 1] === '}' || val[0] === '[' && val[val.length - 1] === ']') {return decomposeStr(val)} else {return val.trim()}}return decomposeStr(jsonData)}
}

测试


console.log('使用自定义反序列化', explamJSon.parse(testStr))
console.log('原生JSON.stringify序列化自定义反序列化结果', JSON.parse(testStr))

能够在原生与自定义之间转换。
在这里插入图片描述
异常判断

const explamJSon = new CustomJson()
// 非合法json字符串
console.log('异常判断', explamJSon.parse('1111'))
// 非合法对象
console.log('异常判断', explamJSon.stringify('1111'))

在这里插入图片描述

四,总结

总的来说,javaScript对的序列化过程是对象的解析,以字符串形式存储对象结构。反序列化是解析字符串,还原成对象。理解这个过程,有助于我们解决复杂问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/665345.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

新书速览|Python数据科学应用从入门到精通

系统教授数据科学与Python实战&#xff0c;涵盖线性回归、逻辑回归、决策树、随机森林、神经网 本书内容 随着数据存储、数据处理等大数据技术的快速发展&#xff0c;数据科学在各行各业得到广泛的应用。数据清洗、特征工程、数据可视化、数据挖掘与建模等已成为高校师生和职场…

STL——空间配置器

空间配置器是STL六大组件之一&#xff0c;它和其他五个组件相互配合&#xff0c;起着很关键的作用。 容器&#xff1a;各种数据结构、如vector、list、stack、deque、queue、set、map、unordered_map等等算法&#xff1a;各种算法&#xff0c;如sort、serach、copy、erase 提供…

C#用正则表达式验证格式:电话号码、密码、邮编、手机号码、身份证、指定的小数点后位数、有效月、有效日

正则表达式在程序设计中有着重要的位置&#xff0c;经常被用于处理字符串信息。 用Regex类的IsMatch方法&#xff0c;使用正则表达式可以验证电话号码是否合法。 一、涉及到的知识点 Regex类的IsMatch方法用于指示正则表达式使用pattern参数中指定的正则表达式是否在输入字符串…

计算机网络_1.6.2 计算机网络体系结构分层的必要性

1.6.2 计算机网络体系结构分层的必要性 一、五层原理体系结构每层各自主要解决什么问题1、物理层2、数据链路层3、网络层4、运输层5、应用层 二、总结三、练习 笔记来源&#xff1a; B站 《深入浅出计算机网络》课程 本节主要介绍实现计算机网络需要解决哪些问题&#xff1f;以…

这种学习单片机的顺序是否合理?

这种学习单片机的顺序是否合理&#xff1f; 在开始前我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「单片机的资料从专业入门到高级教程」&#xff0c; 点个关注在评论区回复“888”之后私信回复“888”&#xff0c;全部无偿共享给大家&#xff01;&#xff01…

随着网络的快速发展,网络安全问题也日益凸显,遇到攻击该如何处理,如何抉择合适的防护方案

DexunCloud 经过研究发现当今世界&#xff0c;随着网络的快速发展&#xff0c;网络安全问题也日益凸显。其中&#xff0c;DDoS&#xff08;分布式拒绝服务&#xff09;攻击被认为是网络安全领域里最为严重的威胁之一。毫无疑问&#xff0c;DDoS攻击不仅可以导致网络服务中断&am…

支付宝直连商户处理支付交易投诉管理,支持多商户

大家好&#xff0c;我是小悟 1、问题背景 玩过支付宝生态的&#xff0c;或许就有这种感受&#xff0c;如果收到投诉单&#xff0c;不会通知到手机端&#xff0c;只会在支付宝商家后台-账号中心-安全中心-消费者投诉-支付交易投诉那里显示。那你能一直盯着电脑看吗&#xff1f;…

Flink CEP(基本概念)

Flink CEP 在Flink的学习过程中&#xff0c;我们已经掌握了从基本原理和核心层的DataStream API到底层的处理函数&#xff0c;再到应用层的Table API和SQL的各种手段&#xff0c;可以应对实际应用开发的各种需求。然而&#xff0c;在实际应用中&#xff0c;还有一类更为复…

AI Partition(银灿U盘分区工具)V2.0.0.3

AI Partition(银灿U盘分区工具)V2.0.0.3.zip 复制链接下载吧 https://url20.ctfile.com/f/36743220-1017367709-67f1b9?p2024 (访问密码: 2024) 支持IS903B IS902E IS916 AI Partition(银灿U盘分区量产工具) 这个是银灿官方发布的最新版U盘分区工具&#xff0c;版本号V2.0.0…

翻转二叉树

226. 翻转二叉树 已解答 简单 相关标签 相关企业 给你一棵二叉树的根节点 root &#xff0c;翻转这棵二叉树&#xff0c;并返回其根节点。 示例 1&#xff1a; 输入&#xff1a;root [4,2,7,1,3,6,9] 输出&#xff1a;[4,7,2,9,6,3,1]示例 2&#xff1a; 输入&#xff1a…

从零学习Linux操作系统 第二十五部分 文本处理工具

一、grep命令的基本使用方法及常用参数介绍 grep [全称&#xff1a;Globally search a Regular Expression and Print 全局搜索正则表达式并打印 ] grep 命令格式 grep 匹配条件 处理文件 grep root passwd过滤root关键字grep -i root passwd后略大小写grep -E “<root”…

嵌入式中物联网核心技术有哪些

IoT军事技术 物联网军事技术是一项利用IoT感知技术在军事活动中获取人、装备、作战环境状态的信息特征&#xff0c;从而实现在军事活动中做出智能化决策和控制局势的军事方针。 据悉&#xff0c;早于2012年10月军方联合了社会研究机构合力创建了“军事物联网联合实验室”。 …

C++核心deque容器,stack容器,queue容器,list容器,set容器,pair ,map容器

3.deque容器 1.deque容器的基本概念 Vector容器是单向开口的连续内存空间&#xff0c;deque则是一种双向开口的连续线性空间。所谓的双向开口&#xff0c;意思是可以在头尾两端插入元素&#xff0c;但是在其头部操作效率奇差&#xff0c;无法被接受。 deque容器和vector容器最…

C++类和对象入门(二)

顾得泉&#xff1a;个人主页 个人专栏&#xff1a;《Linux操作系统》 《C从入门到精通》 《LeedCode刷题》 键盘敲烂&#xff0c;年薪百万&#xff01; 一、类的作用域 类定义了一个新的作用域&#xff0c;类的所有成员都在类的作用域中。在类体外定义成员时&#xff0c;需要…

vue3快速入门

文章目录 1. Vue3简介1.1. 性能的提升1.2.源码的升级1.3. 拥抱TypeScript1.4. 新的特性 2. 创建Vue3工程2.1. 基于 vue-cli 创建2.2. 基于 vite 创建&#xff08;推荐&#xff09;vite介绍创建步骤项目结构安装插件项目结构总结 2.3. 一个简单的效果Person.vueApp.vue 3. Vue3核…

关于爬取所有哔哩哔哩、任意图片、所有音乐、的python脚本语言-Edge浏览器插件 全是干货!

这些都是现成的并且实时更新的&#xff01;从次解放双手&#xff01; 首先有自己的edge浏览器基本上都有并且找到插件选项 1.哔哩哔哩视频下载助手&#xff08;爬取哔哩哔哩视频&#xff09; bilibili哔哩哔哩视频下载助手 - Microsoft Edge Addons 下面是效果&#xff1a; 2.图…

2024年数学建模美赛 A~E 题目解析

2024美赛A题&#xff1a;资源可用性和性别比例 背景 尽管一些动物物种不属于通常的雄性或雌性&#xff0c;大多数物种在出生时要么显著地为雄性&#xff0c;要么为雌性。虽然许多物种在出生时表现出1:1的性别比&#xff0c;但其他物种则偏离了这个均衡的性别比例。这被称为性…

PostgreSQL 也很强大,为何在中国大陆,MySQL 成为主流,PostgreSQL 屈居二线呢?

问题&#xff1a; PostgreSQL 也很强大&#xff0c;为何在中国大陆&#xff0c;MySQL 成为主流&#xff0c;PostgreSQL 屈居二线呢&#xff1f;PostgreSQL 能否替代 MySQL&#xff1f; 当我们讨论为何 MySQL 在中国大陆成为主流而 PostgreSQL 屈居二线时&#xff0c; 我们其实…

高中数学立体几何练习题3

用到的基础知识&#xff1a; 1. 2.

软件测试过程中出现随机性缺陷,大家是如何处理的?

软件测试是确保软件产品的质量、功能和可靠性的关键过程。然而&#xff0c;测试并不总是完美无缺的&#xff0c;在开发和测试阶段可能会出现缺陷。缺陷是错误、缺陷或偏离软件的预期行为或要求。在本文中&#xff0c;我们将探讨软件测试中缺陷的常见类型和原因&#xff0c;以及…