递归JSON.stringify实现 [英] recursive JSON.stringify implementation

查看:178
本文介绍了递归JSON.stringify实现的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试学习Javascript中的递归,所以我想我会使用递归作为对自己的挑战来重写本机 JSON.stringify 函数。我几乎得到了我的代码:

I am trying to learn recursion in Javascript, so I figured I'd rewrite the native JSON.stringify function using recursion as a challenge to myself. I almost got my code to work:

var my_stringify = function(obj){        
  value = obj[ Object.keys(obj)[0] ];
  index = Object.keys(obj)[0];

  delete obj[ Object.keys(obj)[0] ];

  // The value is just a simple string, not a nested object
  if (typeof value === 'string'){
    if (Object.keys(obj).length !== 0){
      // Continue recursion ..
      return '"' + index + '":"' + value + '",' + my_stringify(obj);
    }

    // This would be the base case with a string at the end. Stop recursion.
    return '"' + index + '":"' + value + '"}';
  }
  // The value is actually a nested object
  else{     
    if (Object.keys(obj).length !== 0){
    // Continue recursion ..
      return '"' + index + '":{' + my_stringify(value) + ',' + my_stringify(obj);
    }
    // This is the base case with a nested object at the end. Stringify it and end recursion.
    return '"' + index + '":{' + my_stringify(value) + '}';  
  }
}

除了第一个<$ c $我的答案中缺少c> {,我无法弄清楚如何解决这个问题。

Except for the fact that the first { in my answer is missing, and I can't figure out how to fix this bug.

例如。 my_stringify({foo:'bar'})返回foo:bar} 而不是 {foo:bar}

另外,我知道我完全摧毁了原始物体,有没有办法发送到递归减少版本的原始对象而不删除任何东西(类似 obj.slice(1))?

Also, I'm aware I'm completely destroying the original object, is there any way to send over to recursion a reduced version of the original object without deleting anything (something like obj.slice(1))?

我们将非常感谢任何建议!

Any advice will be greatly appreciated !

推荐答案

旧问题的新答案

这里有一些非常糟糕的答案,即使是最简单的例子也是如此。这个答案的目的是详尽地回答这个问题,并演示如何处理各种数据类型和...这样的方法可以扩展...

There's some painfully bad answers here that fail under even the simplest examples. This answer aims to answer the question exhaustively and demonstrate how an approach like this scales even when handling a wide variety of data types and ...

角点案例

此函数对非空数据的构造函数属性进行简单的案例分析,并进行相应的编码。它设法涵盖了你不太可能考虑的许多极端情况,例如

This function does a simple case analysis on a non-null data's constructor property and encodes accordingly. It manages to cover a lot of corner cases that you're unlikely to consider, such as


  • JSON.stringify (未定义)返回 undefined

  • JSON.stringify(null)返回'null'

  • JSON.stringify(true)返回'true'

  • JSON.stringify([1,2,undefined,4]) 返回'[1,2,null,4]'

  • JSON .stringify({a:undefined,b:2})返回'{b:2}'

  • JSON.stringify({[undefined]:1})返回'{undefined:1}'

  • JSON.stringify({a:/ foo /})返回 {a: {}}

  • JSON.stringify(undefined) returns undefined
  • JSON.stringify(null) returns 'null'
  • JSON.stringify(true) returns 'true'
  • JSON.stringify([1,2,undefined,4]) returns '[1,2,null,4]'
  • JSON.stringify({a: undefined, b: 2}) returns '{ "b": 2 }'
  • JSON.stringify({[undefined]: 1}) returns '{ "undefined": 1 }'
  • JSON.stringify({a: /foo/}) returns { "a": {} }

所以验证我们的 stringifyJSON 函数实际上工作正常,我不打算直接测试它的输出。相反,我将编写一个小的测试方法,以确保我们编码的JSON的 JSON.parse 实际返回我们的原始输入值

So to verify that our stringifyJSON function actually works properly, I'm not going to test the output of it directly. Instead, I'm going to write a little test method that ensures the JSON.parse of our encoded JSON actually returns our original input value

// we really only care that JSON.parse can work with our result
// the output value should match the input value
// if it doesn't, we did something wrong in our stringifier
const test = data => {
  return console.log(JSON.parse(stringifyJSON(data)))
}

test([1,2,3])     // should return [1,2,3]
test({a:[1,2,3]}) // should return {a:[1,2,3]}




免责声明:很明显,我要分享的代码不是意味着用作 JSON.stringify 的实际替代 - 我们可能没有解决过无数的角落案例。相反,这个代码是共享的,以提供我们如何进行此类任务的演示。额外的角落案例可以轻松添加到此功能。

Disclaimer: it should be obvious that the code I'm about to share is not meant to be used as an actual replacement for JSON.stringify – there's countless corner cases we probably didn't address. Instead, this code is shared to provide a demonstration for how we could go about such a task. Additional corner cases could easily be added to this function.






Runnable demo

不用多说,这里有一个可运行的演示中的 stringifyJSON ,可以验证几个常见的兼容性case

Without further ado, here is stringifyJSON in a runnable demo that verifies excellent compatibility for several common cases

const stringifyJSON = data => {
  if (data === undefined)
    return undefined
  else if (data === null)
    return 'null'
  else if (data.constructor === String)
    return '"' + data.replace(/"/g, '\\"') + '"'
  else if (data.constructor === Number)
    return String(data)
  else if (data.constructor === Boolean)
    return data ? 'true' : 'false'
  else if (data.constructor === Array)
    return '[ ' + data.reduce((acc, v) => {
      if (v === undefined)
        return [...acc, 'null']
      else
        return [...acc, stringifyJSON(v)]
    }, []).join(', ') + ' ]'
  else if (data.constructor === Object)
    return '{ ' + Object.keys(data).reduce((acc, k) => {
      if (data[k] === undefined)
        return acc
      else
        return [...acc, stringifyJSON(k) + ':' + stringifyJSON(data[k])]
    }, []).join(', ') + ' }'
  else
    return '{}'
}

// round-trip test and log to console
const test = data => {
  return console.log(JSON.parse(stringifyJSON(data)))
}

test(null)                               // null
test('he said "hello"')                  // 'he said "hello"'
test(5)                                  // 5
test([1,2,true,false])                   // [ 1, 2, true, false ]
test({a:1, b:2})                         // { a: 1, b: 2 }
test([{a:1},{b:2},{c:3}])                // [ { a: 1 }, { b: 2 }, { c: 3 } ]
test({a:[1,2,3], c:[4,5,6]})             // { a: [ 1, 2, 3 ], c: [ 4, 5, 6 ] }
test({a:undefined, b:2})                 // { b: 2 }
test({[undefined]: 1})                   // { undefined: 1 }
test([[["test","mike",4,["jake"]],3,4]]) // [ [ [ 'test', 'mike', 4, [ 'jake' ] ], 3, 4 ] ]

这篇关于递归JSON.stringify实现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆