学透JSON.stringify

10907次阅读 824人点赞 作者: WuBin 发布时间: 2021-10-11 10:08:59
扫码到手机查看

基本概念

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

以下信息来自MDN

语法

JSON.stringify(value[, replacer [, space]])

参数

  • value

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

  • 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序列化).
  • 基本使用

    经常使用JSON.stringify在vue中对对象进行深拷贝。对数据副本进行编辑。

    注意

    1. JSON.stringify可以转换对象或者值(平常用的更多的是转换对象)
    2. 可以指定replacer为函数选择性的地替换
    3. 也可以指定replacer为数组,可转换指定的属性

    这里仅仅是MDN上关于JSON.stringify其中最基础的说明,咱们先打个码试试这几个特性

    // 1. 转换对象
    console.log(JSON.stringify({ name: 'wubin.work', sex: 'boy' })) // '{"name":"wubin.work","sex":"boy"}'
    
    // 2. 转换普通值
    console.log(JSON.stringify('wubin.work')) // "wubin.work"
    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: 'wubin.work', sex: 'boy', age: 100 }, (key, value) => {
      return typeof value === 'number' ? undefined : value
    }))
    // '{"name":"wubin.work","sex":"boy"}'
    
    // 4. 指定数组
    console.log(JSON.stringify({ name: 'wubin.work', sex: 'boy', age: 100 }, [ 'name' ]))
    // '{"name":"wubin.work"}'
    
    // 5. 指定space(美化输出)
    console.log(JSON.stringify({ name: 'wubin.work', sex: 'boy', age: 100 }))
    // '{"name":"wubin.work","sex":"boy","age":100}'
    console.log(JSON.stringify({ name: 'wubin.work', sex: 'boy', age: 100 }, null , 2))
    /*
    {
      "name": "wubin.work",
      "sex": "boy",
      "age": 100
    }
    */

    例如,对一个对象执行一个过滤函数,将value字段值等于undefined的替换为空:

    let signInfo = [
      {
        fieldId: 539,
        value: undefined
      },
      {
        fieldId: 540,
        value: undefined
      },
      {
        fieldId: 546,
        value: undefined
      },
    ]
    
    // 判断到value为undefined,返回空字符串即可
    JSON.stringify(signInfo, (key, value) => typeof value === 'undefined' ? '' : value)
    // '[{"fieldId":539,"value":""},{"fieldId":540,"value":""},{"fieldId":546,"value":""}]'

    9大特性要记住

    前仅仅是使用了这个方法,却没有详细了解他的转换规则,居然有9个之多。

    特性一

    1. undefined任意的函数以及symbol值,出现在非数组对象的属性值中时在序列化过程中会被忽略
    2. undefined任意的函数以及symbol值出现在数组中时会被转换成 null
    3. undefined任意的函数以及symbol值单独转换时,会返回 undefined
    // 1. 对象中存在这三种值会被忽略
    console.log(JSON.stringify({
      name: 'wubin.work',
      sex: 'boy',
      // 函数会被忽略
      showName () {
        console.log('wubin.work')
      },
      // undefined会被忽略
      age: undefined,
      // Symbol会被忽略
      symbolName: Symbol('wubin.work')
    }))
    // '{"name":"wubin.work","sex":"boy"}'
    
    // 2. 数组中存在着三种值会被转化为null
    console.log(JSON.stringify([
      'wubin.work',
      'boy',
      // 函数会被转化为null
      function showName () {
        console.log('wubin.work')
      },
      //undefined会被转化为null
      undefined,
      //Symbol会被转化为null
      Symbol('wubin.work')
    ]))
    // '["wubin.work","boy",null,null,null]'
    
    // 3.单独转换会返回undefined
    console.log(JSON.stringify(
      function showName () {
        console.log('wubin.work')
      }
    )) // undefined
    console.log(JSON.stringify(undefined)) // undefined
    console.log(JSON.stringify(Symbol('wubin.work'))) // undefined

    特性二

    布尔值数字字符串的包装对象在序列化过程中会自动转换成对应的原始值。
    console.log(JSON.stringify([new Number(1), new String("wubin.work"), new Boolean(false)]))
    // '[1,"wubin.work",false]'
    

    特性三

    所有以symbol为属性键的属性都会被完全忽略掉,即便replacer参数中强制指定包含了它们。
    console.log(JSON.stringify({
      name: Symbol('wubin.work'),
    }))
    // '{}'
    console.log(JSON.stringify({
      [ Symbol('wubin.work') ]: 'wubin.work',
    }, (key, value) => {
      if (typeof key === 'symbol') {
        return value
      }
    }))
    // undefined
    

    特性四

    NaN 和 Infinity 格式的数值及 null 都会被当做 null。
    console.log(JSON.stringify({
      age: NaN,
      age2: Infinity,
      name: null
    }))
    // '{"age":null,"age2":null,"name":null}'
    

    特性五

    转换值如果有 toJSON() 方法,该方法定义什么值将被序列化。
    const toJSONObj = {
      name: 'wubin.work',
      toJSON () {
        return 'JSON.stringify'
      }
    }
    
    console.log(JSON.stringify(toJSONObj))
    // "JSON.stringify"

    特性六

    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"

    特性七

    对包含循环引用的对象(对象之间相互引用,形成无限循环)执行此方法,会抛出错误。
    let cyclicObj = {
      name: 'wubin.work',
    }
    
    cyclicObj.obj = cyclicObj
    
    console.log(JSON.stringify(cyclicObj))
    // Converting circular structure to JSON

    特性八

    其他类型的对象,包括 Map/Set/WeakMap/WeakSet,仅会序列化可枚举的属性
    let enumerableObj = {}
    
    Object.defineProperties(enumerableObj, {
      name: {
        value: 'wubin.work',
        enumerable: true
      },
      sex: {
        value: 'boy',
        enumerable: false
      },
    })
    
    console.log(JSON.stringify(enumerableObj))
    // '{"name":"wubin.work"}'

    特性九

    当尝试去转换BigInt类型的值会抛出错误
    const alsoHuge = BigInt(9007199254740991)
    
    console.log(JSON.stringify(alsoHuge))
    // TypeError: Do not know how to serialize a BigInt

    相关资料

    点赞 支持一下 觉得不错?客官您就稍微鼓励一下吧!
    关键词:JSON.stringify
    推荐阅读
    • uniapp实现被浏览器唤起的功能

      当用户打开h5链接时候,点击打开app若用户在已经安装过app的情况下直接打开app,若未安装过跳到应用市场下载安装这个功能在实现上主要分为两种场景,从普通浏览器唤醒以及从微信唤醒。

      9664次阅读 631人点赞 发布时间: 2022-12-14 16:34:53 立即查看
    • Vue

      盘点Vue2和Vue3的10种组件通信方式

      Vue中组件通信方式有很多,其中Vue2和Vue3实现起来也会有很多差异;本文将通过选项式API组合式API以及setup三种不同实现方式全面介绍Vue2和Vue3的组件通信方式。

      4342次阅读 322人点赞 发布时间: 2022-08-19 09:40:16 立即查看
    • JS

      几个高级前端常用的API

      推荐4个前端开发中常用的高端API,分别是MutationObserver、IntersectionObserver、getComputedstyle、getBoundingClientRect、requ...

      14542次阅读 951人点赞 发布时间: 2021-11-11 09:39:54 立即查看
    • PHP

      【正则】一些常用的正则表达式总结

      在日常开发中,正则表达式是非常有用的,正则表达式在每个语言中都是可以使用的,他就跟JSON一样,是通用的。了解一些常用的正则表达式,能大大提高你的工作效率。

      13594次阅读 496人点赞 发布时间: 2021-10-09 15:58:58 立即查看
    • 【中文】免费可商用字体下载与考证

      65款免费、可商用、无任何限制中文字体打包下载,这些字体都是经过长期验证,经得住市场考验的,让您规避被无良厂商起诉的风险。

      12136次阅读 971人点赞 发布时间: 2021-07-05 15:28:45 立即查看
    • Vue

      Vue3开发一个v-loading的自定义指令

      在vue3中实现一个自定义的指令,有助于我们简化开发,简化复用,通过一个指令的调用即可实现一些可高度复用的交互。

      16475次阅读 1315人点赞 发布时间: 2021-07-02 15:58:35 立即查看
    • JS

      关于手机上滚动穿透问题的解决

      当页面出现浮层的时候,滑动浮层的内容,正常情况下预期应该是浮层下边的内容不会滚动;然而事实并非如此。在PC上使用css即可解决,但是在手机端,情况就变的比较复杂,就需要禁止触摸事件才可以。

      15243次阅读 1240人点赞 发布时间: 2021-05-31 09:25:50 立即查看
    • Vue

      Vue+html2canvas截图空白的问题

      在使用vue做信网单页专题时,有海报生成的功能,这里推荐2个插件:一个是html2canvas,构造好DOM然后转canvas进行截图;另外使用vue-canvas-poster(这个截止到2021年3月...

      30010次阅读 2359人点赞 发布时间: 2021-03-02 09:04:51 立即查看
    • Vue

      vue-router4过度动画无效解决方案

      在初次使用vue3+vue-router4时候,先后遇到了过度动画transition进入和退出分别无效的情况,搜遍百度没没找到合适解决方法,包括vue-route4有一些API都进行了变化,以前的一些操...

      26052次阅读 2003人点赞 发布时间: 2021-02-23 13:37:20 立即查看
    交流 收藏 目录