我正在尝试复制json stringify方法,而是使用递归。我已经能够传递很多测试用例但是当涉及到嵌套数组时,我似乎遇到了问题。如果数组中有任何空数组('[]'),我得到类似[,7,9]而不是[[],7,9]的东西。如果我传入的话:
stringifyJSON([[["test","mike",4,["jake"]],3,4]])
"[[test,mike,4,jake,3,4]]"
我认为我已经接近了这个工作,但我可能不得不重新开始。你们有什么想法我可以改变什么来使这个工作嵌套的例子?这是我现在的代码:
var testarray = [9,[[],2,3]] //should return '[9,[[],2,3]]'
var count = 0
var stringifyJSON = function(obj,stack) {
var typecheck = typeof obj;
var resarray = stack;
if(resarray == null){ //does resarray exist? Is this the first time through?
var resarray = [];
}
if(typeof obj === "string"){ //Is obj a string?
return '"' + String(obj) + '"';
}
if((Array.isArray(obj)) && (obj.length > 0)){ //If not a string, is it an object?
for(var i = 0; i<obj.length;i++){
if(Array.isArray(obj[i])){
var arraytemp = []
stringifyJSON(arraytemp.push(obj[i]),resarray) // this is probably incorrect, this is how i handle a nested array situation
}
if(typeof obj[i] === 'number'){ //if the number is inside of the array, don't quote it
resarray.push(obj[i]);
}
else if(typecheck === 'object' && Array.isArray(obj[0])){
resarray.push('[' + obj[i] + ']');
}
else{
resarray.push('"' + obj[i] + '"');
}
obj.shift() //delete the first object in the array and get ready to recurse to get to the second object.
stringifyJSON(obj,resarray); //remember the new array when recursing by passing it into the next recursive instance
}
}
if(obj !== null && typeof obj === 'object'){ //is obj an object?
for(var key in obj){
stringifyJSON(resarray.push(key + '"' + ':' + obj[key]),resarray)
}
}
if(typeof obj === "number" || obj == null || obj === true || obj === false){ //special cases and if it's a number
return '' + obj + ''
}
if(typecheck === 'object'){ //a special case where you have an empty array that needs to be quoted.
return '['+resarray+']'
}
return '' + resarray.join('') + '';
};
//JSON values cannot be a function, a date, or undefined
答案 0 :(得分:2)
你们对于我可能能够改变什么以使其适用于嵌套示例有什么想法吗?
当然,但它会废弃你的整个功能,所以我希望你不要介意。我将提供一个点清单,说明为什么这种方法是必不可少的,而你的基本上有缺陷从一开始 :(
转角案件
此函数对非空数据的constructor
属性进行简单的案例分析,并进行相应编码。它设法涵盖了您不太可能考虑的许多极端案例,例如
JSON.stringify(undefined)
返回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({a: /foo/})
返回{ "a": {} }
因此,为了验证我们的stringifyJSON
函数实际上是否正常工作,我不会直接测试它的输出。相反,我将编写一个小test
方法,以确保我们编码的JSON的JSON.parse
实际返回我们的原始输入值
// 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
的实际替代 - 我们可能无法解决的无数角落案例。相反,这个代码是共享的,以提供我们如何进行此类任务的演示。可以轻松地将其他角落案例添加到此功能中。
Runnable演示
不用多说,这里有一个可运行的演示中的stringifyJSON
,可以验证几种常见情况的出色兼容性
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([[["test","mike",4,["jake"]],3,4]]) // [ [ [ 'test', 'mike', 4, [ 'jake' ] ], 3, 4 ] ]
&#13;
&#34;为什么这样更好?&#34;
null
和undefined
s,等等 - 你明白了stringifyJSON
对象的每个案例就像一个小程序,告诉我们如何编码每种类型(例如String
,Number
,Array
,{{1等等)Object
类型检查 - 在我们检查typeof
和undefined
个案后,我们知道我们可以尝试阅读null
属性。constructor
,if
,&&
或检查||
等内容时没有复杂的!
条件x > y.length
或obj[0]
obj[i]
属性length
或在resarray
次呼叫发生后的状态该计划的各个阶段自定义对象
push
允许我们在自定义对象上设置JSON.stringify
属性,这样当我们对它们进行字符串化时,我们就会得到我们想要的结果。
toJSON
&#13;
我们可以轻松地将这种功能添加到上面的代码中 - 更改粗体
const Foo = x => ({
toJSON: () => ({ type: 'Foo', value: x })
})
console.log(JSON.stringify(Foo(5)))
// {"type":"Foo","value":5}
答案 1 :(得分:0)
因此,在使用您的代码后,我发现如果您更换:
git commit --amend
with:
resarray.push('[' + obj[i] + ']');
它适用于数组并且仍然满足您的递归过程。
此外,我发现有一些怪癖通过像resarray.push(stringifyJSON(obj[i]))
这样的对象运行它,并发现通过改变对象的字符串化来:
{ hello: 5, arr: testarray, arr2: [1, 2,3, "hello"], num: 789, str: '4444', str2: "67494" };
更像是:
stringifyJSON(resarray.push(key + '"' + ':' + obj[key]),resarray)
它应该更多地锻炼你想要的东西。这真的很酷,我玩得很开心!