基本介绍

JSON的全称是JavaScript Object Notation,它并不是编程语言,而是一种可以在服务器和客户端之间传输的数据格式,本来是JavaScript的子集,但现在已独立存在于各种编程语言中。

它有以下使用场景

  • 网络数据传递时,比如http请求中参数
  • 项目里某些配置文件,比如package.json文件
  • 非关系型数据库(NoSQL)将json作为存储格式

语法

它的文件以 .json 为后缀名,但json文件顶层的代码有严格限制,只能写以下三种,不然代码会直接标红~

1、简单值

数字(Number)、字符串(String,不支持单引号)、布尔类型(Boolean)、null类型

2、对象值

由key、value组成,key是字符串类型,必须添加双引号,值可以是简单值、对象值、数组值

3、数组值

简单值、对象值、数组值

序列化 stringify

在http请求中携带参数经常用到json格式,但我们一般不会在代码中直接使用json,因为json数据中操作属性并不方便,大多数时候是使用对象,将对象转成json格式就可以通过 stringify 方法。

stringify方法有三个参数

  • 参数一(必传),传入一个对象,表示对于哪个对象进行stringify操作
  • 参数二(可选),传入数组或者函数,数组里包括对象的key值,表示对于对象中的指定key值的数据进行序列化,传入函数表示对指定的key/value值进行操作
  • 参数三(可选),用于改变序列化之后的json数据展现格式

我们对以下对象进行操作

const user = {
  name: "alice",
  age: 20,
  friends: ["lisa", "macus", "windy"],
  info: {
    teacher: "kiki",
  },
};
直接转换

当只传入一个参数时,进行基本的序列化操作

const str1 = JSON.stringify(user);
console.log(str1);

操作指定的key值
const str2 = JSON.stringify(user, ["name", "friends"]);
const str3 = JSON.stringify(user, (key, value) => {
  if (key === "age") {
    return value + 1;
  }
  return value;
});
console.log(str2);
console.log(str3);

当传入第二个参数时,传入数组,表示只对 key值为“name”,“friends”的数据进行序列化;传入函数,表示操作 key 值为“age”的时候,value+1

改变json展现格式
const str4 = JSON.stringify(user, null, 2);
const str5 = JSON.stringify(user, null, "*");
console.log(str4);
console.log(str5);

传入第三个参数,2表示换行空2格,* 表示换行及每行内容前加 * 号

toJson方法

如果原对象中有toJSON方法,那么stringify方法直接调用toJSON方法。我们给上面的对象加上toJSON方法,所有的stringify方法的执行结果都会变化。

const user = {
  name: "alice",
  age: 20,
  friends: ["lisa", "macus", "windy"],
  info: {
    teacher: "kiki",
  },
  toJSON(){
    return 'hello world'
  }
}; const str1 = JSON.stringify(user);
const str2 = JSON.stringify(user, ["name", "friends"]);
const str3 = JSON.stringify(user, (key, value) => {
  if (key === "age") {
    return value + 1;
  }
  return value;
});
const str4 = JSON.stringify(user, null, 2);
const str5 = JSON.stringify(user, null, "*"); console.log(str1);
console.log(str2);
console.log(str3);
console.log(str4);
console.log(str5);

stringify方法的执行结果都变成了 toJSON 方法的返回值

解析 parse

接口请求返回的参数中一般是json数据,我们要使用首先得通过parse方法将它转成对象。

parse方法可以接收两个参数

  • 参数一(必传),json数据,表示将哪一个json数据转成对象
  • 参数二(可选),传入函数,表示对指定的key/value值进行操作
const str =
  '{"name":"alice","age":21,"friends":["lisa","macus","windy"],"info":{"teacher":"kiki"}}'; const obj1 = JSON.parse(str)
const obj2 = JSON.parse(str, (key, value)=>{
  if(key === 'age'){
    return value - 1
  }
  return value
}) console.log(obj1)
console.log(obj2)

传入函数,处理 key值为age时的数据,此时操作 value - 1

拷贝

拷贝有以下几种形式,拷贝出来的内存地址指向不一样

直接赋值

通过等于符号可以将一个对象赋值给另一个对象。

const user = {
  name: "alice",
  info: {
    hobbies: "tennis",
  },
};
const person = user;
user.name = "lisa"; console.log("user", user);
console.log("person", person);

但它们其实指向的是同一个对象,如果操作其中一个对象的值,另外一个对象也会发生变化

在内存中表现如下

浅拷贝

浅拷贝只会遍历一层,如果对象中还有value值为对象或者数组的情况,那么更深一层不会被拷贝,展开运算符或者Object.assign可以进行浅拷贝。

const user = {
  name: "alice",
  info: {
    hobbies: "tennis",
  },
};
const consumer = { ...user };
user.name = "lisa";
user.info.hobbies = "swimming"; console.log("user", user);
console.log("consumer", consumer);

浅拷贝后,user和consumer已经不是同一个对象了,但他们俩当中的info仍然指向同一个对象,修改其中一个info中的属性,另一个也会变化

在内存中表现如下

深拷贝

深拷贝表示拷贝出来的对象与原对象完全无关,操作任意属性都不会互相影响,通过 stringify 和 parse 方法可以实现深拷贝。

const user = {
  name: "alice",
  info: {
    hobbies: "tennis",
  },
}; const human = JSON.parse(JSON.stringify(user));
user.name = "lisa";
user.info.hobbies = "swimming"; console.log("user", user);
console.log("human", human);

此时user和human不是指向同一个对象,他们中的info对象也不是同一个对象

在内存中表现如下

stringify和parse实现深拷贝存在问题

虽然stringify和parse可以实现深拷贝,但是这种方式仍存在一些问题,如果对象中存在【方法、undefined、Symbol】,会直接被移除

const user = {
  name: "alice",
  height: undefined,
  [Symbol("age")]: 20,
  info: {
    hobbies: "tennis",
  },
  study() {
    console.log("I love reading~");
  },
};
const people = JSON.parse(JSON.stringify(user)); console.log("user", user);
console.log("person", people);

只剩下符合json规范的数据

因为存在这种问题,所以一般不会用stringify和parse方法,可以自己编写处理深拷贝的方法,至于自定义深拷贝方法,留在后面的文章中详细介绍。

以上就是json相关内容,关于js高级,还有很多需要开发者掌握的地方,可以看看我写的其他博文,持续更新中~

json虽然简单,但这些细节你未必知道的更多相关文章

  1. json-lib简单处理json和对json的简单介绍

    JSON 1.json是什么? *它是js提供的一种数据交换格式 2.json的语法 *{}:是对象! >属性名必须使用双引号括起来!单引号不行!!! >属性值: *null *数值 *数 ...

  2. js中json数据简单处理(JSON.parse()和js中嵌套html)

    js中json数据简单处理(JSON.parse()和js中嵌套html) 一.总结 1.html中嵌套js:<script>js代码</script> 2.js中嵌套html ...

  3. Python中json的简单读写操作

    Python中json的简单读写操作 JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式.它基于ECMAScript的一个子集. JSON采用完全独立于语言的 ...

  4. golang json 包简单分析

    首先上代码: func main() { b := true a1, _ := json.Marshal(b) a2, _ := Marshal(b) fmt.Println(string(a1)) ...

  5. JSON.NET 简单的使用

    JSON.NET(http://json.codeplex.com/)使用来将.NET中的对象转换为JSON字符串(序列化?),或者将JSON字符串转换为.NET中已有类型的对象(反序列化?) 首先为 ...

  6. android json 解析 简单示例

    1 下面是一个简单的json 解析的demo,废话不多说,直接上代码 package com.sky.gallery; import java.io.ByteArrayOutputStream; im ...

  7. Android+Servlet+MySql+JSON实现简单的数据查询操作--C/S架构

    本例简单地实现Android客户端与服务器端交互,主要是通过客户端输入内容(学号)提交到服务器端,服务器端与数据库交互去查询相应信息(姓名).根据这个做个完整的安卓登录是没问题的.本例数据库服务器都采 ...

  8. java post请求的表单提交和json提交简单小结

    在java实现http请求时有分为多种参数的传递方式,以下给出通过form表单提交和json提交的参数传递方式: public String POST_FORM(String url, Map< ...

  9. JSON的简单介绍以及C语言的JSON库使用

    JSON概述 JSON: JavaScript 对象表示法( JavaScript Object Notation) .是一种轻量级的数据交换格式. 它基于ECMAScript的一个子集. JSON采 ...

  10. Struts2+json+hignchart(简单柱状图实现--适合jquery小白)

    做了一个简单的基于Struts2 + Json + HighChart的小例子,费了一下午+晚上的时间,虽然简单,但对于我这种Jquery+Ajax小白的人还是很值得记录的. 哈哈哈 # 0. 关键点 ...

随机推荐

  1. 2022-11-29:查找重复的电子邮箱。以下数据中a@b.com是重复的,请写出sql语句。 DROP TABLE IF EXISTS person; CREATE TABLE person (

    2022-11-29:查找重复的电子邮箱.以下数据中a@b.com是重复的,请写出sql语句. DROP TABLE IF EXISTS person; CREATE TABLE person ( i ...

  2. 2021-08-07:与数组中元素的最大异或值。给你一个由非负整数组成的数组 nums 。另有一个查询数组 queries ,其中 queries[i] = [xi, mi] 。第 i 个查询的答案是

    2021-08-07:与数组中元素的最大异或值.给你一个由非负整数组成的数组 nums .另有一个查询数组 queries ,其中 queries[i] = [xi, mi] .第 i 个查询的答案是 ...

  3. 2021-11-01:寻找重复数。给定一个包含 n + 1 个整数的数组 nums ,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数。假设 nums 只有 一个重复的整数

    2021-11-01:寻找重复数.给定一个包含 n + 1 个整数的数组 nums ,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数.假设 nums 只有 一个重复的整数 ...

  4. SpringBoot限制接口访问频率 - 这些错误千万不能犯

    最近在基于SpringBoot做一个面向普通用户的系统,为了保证系统的稳定性,防止被恶意攻击,我想控制用户访问每个接口的频率.为了实现这个功能,可以设计一个annotation,然后借助AOP在调用方 ...

  5. 【python基础】变量

    1.初识变量 编程本质就是通过一定的规则,去操纵数据,变量作为数据的载体,在程序中经常会被用到.与变量相联系的还有一个名词叫数据类型,我们可以举一个生活中的例子,来理解数据类型-变量-数据三者之间的关 ...

  6. bugku xxx二手交易市场

    打开靶场 分析 很明显需要先注册一个账号才行 完成后发现两个上传图片的地方 一个是更换头像, 一个是发布内容 先更换头像试试 首先上传一个木马图片,会发现一直转圈圈,(卡住了) 只能先上传正常的图片了 ...

  7. 龙芯下如何进行.net core程序开发部署

    龙芯LoongArch64已经发布了对.NETCore的支持,相关工具链也已完成,目前支持.NETCore3.1..NET6..NET7版本.本文以.NETCore3.1在loongnix-serve ...

  8. [AGC055A] ABC Identity 题解

    [AGC055A] ABC Identity 题解 题目描述 给定长度为 \(3n (1 \le n \le 2e5)\) 的序列,其中字母 A,B,C 各有 \(n\) 个. 一个合法序列 \(T\ ...

  9. C#里的var和dynamic区别到底是什么,你真的搞懂了嘛

    前言 这个var和dynamic都是不确定的初始化类型,但是这两个本质上的不同.不同在哪儿呢?var编译阶段确定类型,dynamic运行时阶段确定类型.这种说法对不对呢?本篇看下 概括 以下详细叙述下 ...

  10. Hugging News #0626: 音频课程更新、在线体验 baichuan-7B 模型、ChatGLM2-6B 重磅发

    每一周,我们的同事都会向社区的成员们发布一些关于 Hugging Face 相关的更新,包括我们的产品和平台更新.社区活动.学习资源和内容更新.开源库和模型更新等,我们将其称之为「Hugging Ne ...