学透JSON.stringify

  JSON.stringify()方法将一个 JavaScript 对象转换为 JSON 字符串,如果指定了一个 replacer 函数,则可以选择性地替换值,或者指定的 replacer 是数组,则可选择性地仅包含数组指定的属性。

语法

JSON.stringfy(value,replacer,space)

参数 

value

将要序列化成一个JSON字符串的值。

var a = [1,2,3]
var b= JSON.stringify(a)
console.log(b)  //输出结果 "[1,2,3]"

replacer 可选

1. 如果该参数是一个函数,则在序列化过程中,被序列化的值的每个属性都会经过该函数的转换和处理;

2.如果该参数是一个数组,则只有包含在这个数组中的属性名才会被序列化到最终的 JSON 字符串中;

3.如果该参数为 null 或者未提供,则对象所有的属性都会被序列化。

space   可选

1.指定缩进用的空白字符串,用于美化输出(pretty-print)

2.如果参数是个数字,它代表有多少的空格;上限为10。

3.该值若小于1,则意味着没有空格;

4.如果该参数为字符串(当字符串长度超过10个字母,取其前10个字母),该字符串将被作为空格;

5.如果该参数没有提供(或者为 null),将没有空格。

返回值

一个表示定值的JSON字符串

异常

*当在循环引用时会抛出异常TypeError ("cyclic object value")(循环对象值)

*当尝试去转换 BigInt 类型的值会抛出TypeError ("BigInt value can't be serialized in JSON")(BigInt值不能JSON序列化).

基本使用

注意

1.JSON.stringify()可以转换对象或者值(平常用的更多的是转化对象)

2.可以指定 replacer 为函数选择性的替换

3.也可以指定replacer 为数组 可转换的指定属性   

代码示例

// 1. 转换对象
console.log(JSON.stringify({ name: '前端胖头鱼', sex: 'boy' })) // '{"name":"前端胖头鱼","sex":"boy"}'

// 2. 转换普通值
console.log(JSON.stringify('前端胖头鱼')) // "前端胖头鱼"
console.log(JSON.stringify(1)) // "1"
console.log(JSON.stringify(true)) // "true"
console.log(JSON.stringify(null)) // "null"

// 3. 指定replacer函数
console.log(JSON.stringify({ name: '前端胖头鱼', sex: 'boy', age: 100 }, (key, value) => {
  return typeof value === 'number' ? undefined : value
}))
// '{"name":"前端胖头鱼","sex":"boy"}'

// 4. 指定数组
console.log(JSON.stringify({ name: '前端胖头鱼', sex: 'boy', age: 100 }, [ 'name' ]))
// '{"name":"前端胖头鱼"}'

// 5. 指定space(美化输出)
console.log(JSON.stringify({ name: '前端胖头鱼', sex: 'boy', age: 100 }))
// '{"name":"前端胖头鱼","sex":"boy","age":100}'
console.log(JSON.stringify({ name: '前端胖头鱼', sex: 'boy', age: 100 }, null , 2))
/*
{
  "name": "前端胖头鱼",
  "sex": "boy",
  "age": 100
}
*/

 9大特性要记住

特性一

1.undefined任意的函数以及symbol值,出现在非数组对象的属性值中时在序列化过程中会被忽略

2.undefined任意的函数以及symbol值出现在数组中时会被转换成 null

3.undefined任意的函数以及symbol值单独转换时,会返回 undefined

// 1. 对象中存在这三种值会被忽略
console.log(JSON.stringify({
  name: '前端胖头鱼',
  sex: 'boy',
  // 函数会被忽略
  showName () {
    console.log('前端胖头鱼')
  },
  // undefined会被忽略
  age: undefined,
  // Symbol会被忽略
  symbolName: Symbol('前端胖头鱼')
}))
// '{"name":"前端胖头鱼","sex":"boy"}'

// 2. 数组中存在着三种值会被转化为null
console.log(JSON.stringify([
  '前端胖头鱼',
  'boy',
  // 函数会被转化为null
  function showName () {
    console.log('前端胖头鱼')
  },
  //undefined会被转化为null
  undefined,
  //Symbol会被转化为null
  Symbol('前端胖头鱼')
]))
// '["前端胖头鱼","boy",null,null,null]'

// 3.单独转换会返回undefined
console.log(JSON.stringify(
  function showName () {
    console.log('前端胖头鱼')
  }
)) // undefined
console.log(JSON.stringify(undefined)) // undefined
console.log(JSON.stringify(Symbol('前端胖头鱼'))) // undefined

特性二

1.布尔值数字字符串的包装对象在序列化过程中会自动转换成对应的原始值

console.log(JSON.stringify([new Number(1), new String("前端胖头鱼"), new Boolean(false)]))
// '[1,"前端胖头鱼",false]'

特性三

1.所有以symbol为属性键的属性都会被完全忽略掉,即便 replacer 参数中强制指定包含了它们。

console.log(JSON.stringify({
  name: Symbol('前端胖头鱼'),
}))
// '{}'
console.log(JSON.stringify({
  [ Symbol('前端胖头鱼') ]: '前端胖头鱼',
}, (key, value) => {
  if (typeof key === 'symbol') {
    return value
  }
}))
// undefined

特性四

1.NaN 和 Infinity 格式的数值及 null 都会被当做 null。

console.log(JSON.stringify({
  age: NaN,
  age2: Infinity,
  name: null
}))
// '{"age":null,"age2":null,"name":null}'

特性五

转换值如果有 toJSON() 方法,该方法定义什么值将被序列化。

const toJSONObj = {
  name: '前端胖头鱼',
  toJSON () {
    return 'JSON.stringify'
  }
}

console.log(JSON.stringify(toJSONObj))
// "JSON.stringify"

特性六

1.Date 日期调用了 toJSON() 将其转换为了 string 字符串(同Date.toISOString()),因此会被当做字符串处理。

const d = new Date()

console.log(d.toJSON()) // 2021-10-05T14:01:23.932Z
console.log(JSON.stringify(d)) // "2021-10-05T14:01:23.932Z"

特性七

1.对包含循环引用的对象(对象之间相互引用,形成无限循环)执行此方法,会抛出错误。

let cyclicObj = {
  name: '前端胖头鱼',
}

cyclicObj.obj = cyclicObj

console.log(JSON.stringify(cyclicObj))
// Converting circular structure to JSON

特性八

1.其他类型的对象,包括 Map/Set/WeakMap/WeakSet,仅会序列化可枚举的属性

let enumerableObj = {}

Object.defineProperties(enumerableObj, {
  name: {
    value: '前端胖头鱼',
    enumerable: true
  },
  sex: {
    value: 'boy',
    enumerable: false
  },
})

console.log(JSON.stringify(enumerableObj))
// '{"name":"前端胖头鱼"}'

特性九

1.当尝试去转换 BigInt 类型的值会抛出错误

const alsoHuge = BigInt(9007199254740991)

console.log(JSON.stringify(alsoHuge))
// TypeError: Do not know how to serialize a BigInt

手写一个JSON.stringify

const jsonstringify = (data) => {
  // 确认一个对象是否存在循环引用
  const isCyclic = (obj) => {
  // 使用Set数据类型来存储已经检测过的对象
  let stackSet = new Set()
  let detected = false

  const detect = (obj) => {
    // 不是对象类型的话,可以直接跳过
    if (obj && typeof obj != 'object') {
      return
    }
    // 当要检查的对象已经存在于stackSet中时,表示存在循环引用
    if (stackSet.has(obj)) {
      return detected = true
    }
    // 将当前obj存如stackSet
    stackSet.add(obj)

    for (let key in obj) {
      // 对obj下的属性进行挨个检测
      if (obj.hasOwnProperty(key)) {
        detect(obj[key])
      }
    }
    // 平级检测完成之后,将当前对象删除,防止误判
    /*
      例如:对象的属性指向同一引用,如果不删除的话,会被认为是循环引用
      let tempObj = {
        name: '前端胖头鱼'
      }
      let obj4 = {
        obj1: tempObj,
        obj2: tempObj
      }
    */
    stackSet.delete(obj)
  }

  detect(obj)

  return detected
}

  // 特性七:
  // 对包含循环引用的对象(对象之间相互引用,形成无限循环)执行此方法,会抛出错误。
  if (isCyclic(data)) {
    throw new TypeError('Converting circular structure to JSON')
  }

  // 特性九:
  // 当尝试去转换 BigInt 类型的值会抛出错误
  if (typeof data === 'bigint') {
    throw new TypeError('Do not know how to serialize a BigInt')
  }

  const type = typeof data
  const commonKeys1 = ['undefined', 'function', 'symbol']
  const getType = (s) => {
    return Object.prototype.toString.call(s).replace(/\[object (.*?)\]/, '$1').toLowerCase()
  }

  // 非对象
  if (type !== 'object' || data === null) {
    let result = data
    // 特性四:
    // NaN 和 Infinity 格式的数值及 null 都会被当做 null。
    if ([NaN, Infinity, null].includes(data)) {
      result = 'null'
      // 特性一:
      // `undefined`、`任意的函数`以及`symbol值`被`单独转换`时,会返回 undefined
    } else if (commonKeys1.includes(type)) {
      // 直接得到undefined,并不是一个字符串'undefined'
      return undefined
    } else if (type === 'string') {
      result = '"' + data + '"'
    }

    return String(result)
  } else if (type === 'object') {
    // 特性五:
    // 转换值如果有 toJSON() 方法,该方法定义什么值将被序列化
    // 特性六:
    // Date 日期调用了 toJSON() 将其转换为了 string 字符串(同Date.toISOString()),因此会被当做字符串处理。
    if (typeof data.toJSON === 'function') {
      return jsonstringify(data.toJSON())
    } else if (Array.isArray(data)) {
      let result = data.map((it) => {
        // 特性一:
        // `undefined`、`任意的函数`以及`symbol值`出现在`数组`中时会被转换成 `null`
        return commonKeys1.includes(typeof it) ? 'null' : jsonstringify(it)
      })

      return `[${result}]`.replace(/'/g, '"')
    } else {
      // 特性二:
      // 布尔值、数字、字符串的包装对象在序列化过程中会自动转换成对应的原始值。
      if (['boolean', 'number'].includes(getType(data))) {
        return String(data)
      } else if (getType(data) === 'string') {
        return '"' + data + '"'
      } else {
        let result = []
        // 特性八
        // 其他类型的对象,包括 Map/Set/WeakMap/WeakSet,仅会序列化可枚举的属性
        Object.keys(data).forEach((key) => {
          // 特性三:
          // 所有以symbol为属性键的属性都会被完全忽略掉,即便 replacer 参数中强制指定包含了它们。
          if (typeof key !== 'symbol') {
            const value = data[key]
            // 特性一
            // `undefined`、`任意的函数`以及`symbol值`,出现在`非数组对象`的属性值中时在序列化过程中会被忽略
            if (!commonKeys1.includes(typeof value)) {
              result.push(`"${key}":${jsonstringify(value)}`)
            }
          }
        })

        return `{${result}}`.replace(/'/, '"')
      }
    }
  }
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Asp 这个老古懂估计没几个人在用了。几年没写代码了,最近要弄个小东西,给手机端提供json数据,不想麻烦别人,自己又只会asp,没办法就自己动手了。网上找了好久都没有一个人能完整的把asp操作json说清楚。最后还是自己搞定的。整出来共享给大家。(ps,还有个原因csdn的分不够用啦,大家看着给点吧。写这个说明文档都用了我两小时。^_^) 以下是示例代码 '说明:json.asp中引用了json.js.asp '其他见文档 '手机很多时候不认gb2312,跳入json的坑就忘记gb2312吧,讨厌的是,如果代码报错,iis会输出gb2312,结果就是乱码,有点烦。 '自己想办法解决吧 response.Charset= "utf-8" dim strJsonData,ovbJson,j dim arrTemp,varname ,i set ovbJson=new vbJson 'asp recrodset和数组转json字符 arrTemp=array("a","{""oa"":""我是oa""}","c") strJsonData=ovbjson.toJson(empty,arrTemp,true) '转换为Json格式的字符串,有兴趣可以自己输出看看是什么 set j=json.parse(strJsonData) '序列化为json对象(或者是数组对象) response.Write(j.get(1)&"") '别用vb数组来存json对象,不然得每个元素去重新序列化,这里如果想j.get(1).oa就不行了。必须对j.get(1)单独序列才行 '----recrodset就不演示了,懒得连数据库 '---自定义操作方法的演示--- strJsonData="{a:1,b:[{c:'我是数组中的点c'}]}" set j=json.parsestr(strJsonData) response.Write(j.b.get(0).c&"") '添加节点的时候注意,如果值是null,会被忽然,这个节点会不存在的。在添加之前记得先检查值 set j=json.add(j,"new","我是新加的节点") response.Write(j.new&"") '下面这句注掉了,是因为这个操作是无效的因为j.b是数组,不能add 'set j=json.add(j.b,"new1","我是加不进的节点") set j.b=j.b.put(j.b.length,j.b.get(0)) response.Write(j.b.get(1).c&",我是新加的数组元素") '因为数组的get方法不允许被赋值,所以不能像下面这样写 'set j.b.get(0)=json.add(j.b.get(0),"new","我会报错") json.add j.b.get(0),"new","我是新加的new我不会报错" json.add j.b.get(0),"new1","我是通过变量取出来的哦" response.Write(j.b.get(0).new&"") varname="new1" response.Write(json.byname(j.b.get(0),varname)&"") for i=0 to j.b.length-1 varname="c" response.Write(json.byname(j.b.get(i),varname)&"我是循环出来的c,索引:"&i&" ") next '最后完整的输出给手机就这样: response.Write json.stringify(j)
JSON.parse(JSON.stringify(obj))是一种将JavaScript对象转换为JSON字符串再转回JavaScript对象的常见方法。在这个过程中,JSON.stringify()方法将JavaScript对象转换为JSON字符串,而JSON.parse()方法则将JSON字符串转换回JavaScript对象。 这种方法的主要用途是在JavaScript中对对象进行深拷贝。通过先将对象转换为JSON字符串,然后再将其转换回对象,可以创建一个原始对象的副本,而不是只是引用原始对象。 例如,假设我们有一个包含复杂嵌套结构的JavaScript对象obj,我们想要创建它的副本。我们可以使用JSON.parse(JSON.stringify(obj))来实现这一目标。 这种方法的好处是它可以处理几乎所有类型的JavaScript对象,包括数组、函数和日期对象等。 但需要注意的是,JSON.stringify()方法会忽略对象的某些属性,例如函数和原型链上的属性。因此,通过JSON.parse(JSON.stringify(obj))进行深拷贝时,可能会丢失一些对象的特定行为。 此外,在使用JSON.parse()和JSON.stringify()方法时,需要确保处理的对象是有效的JSON格式。如果对象中包含不支持的数据类型或循环引用,这些方法可能会导致错误。 总结起来,JSON.parse(JSON.stringify(obj))是一种将JavaScript对象转换为JSON字符串再转回JavaScript对象的方法,用于实现对象的深拷贝。但需要注意处理的对象应为有效的JSON格式,并且一些特定类型的属性可能会丢失。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [了解 JSON.parse() 和 JSON.stringify()](https://blog.csdn.net/allway2/article/details/123856863)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *3* [关于JSON.parse(),JSON.stringify(),jQuery.parseJSON()的用法](https://download.csdn.net/download/weixin_38743391/13002642)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值