如何通过JSON的替换函数对对象进行字符串化?

时间:2015-05-16 20:17:24

标签: javascript json

这是我的代码:

BAD = {
          "a": "2",
          "b": 1,
          "c": "Nexus",
          "d": "Alligator",
          "e": 5,
          "f": 1431807036,
          "g": {
                    "2": {
                            "w": 17,
                            "b": 5
                         }
               }
      }

console.log(JSON.stringify(BAD, ['a', 'b', 'c', 'd', 'e', 'g']));

http://jsfiddle.net/whv7x6xc/1/

密钥abcdeg是唯一被字符串化的密钥,但有一个问题。它忽略了分配给g的对象。

enter image description here

但是,如果你这样做:console.log(JSON.stringify(BAD));它会显示正确的字符串化版本。

编辑:wb并且动态并定期更改(来来去去),所以我不能只是对它们进行硬编码。

3 个答案:

答案 0 :(得分:6)

JSON替换器是递归的。这意味着它为所遇到的所有对象使用相同的数组。换句话说,它使用相同的值来映射BAD.g的值。由于Bad.g的值没有与您提供的键匹配的任何键,因此无法正确映射任何内容。这意味着我们必须添加" 2"你的阵列。现在" 2"还有一个具有不同键的对象。我们已经考虑了" b",所以现在我们只需要添加" w"你的阵列。

在为替换者提供数组时,最好将数组视为所有要映射的键的列表。

DEMO:http://jsfiddle.net/dirtyd77/whv7x6xc/4/

console.log(JSON.stringify(BAD, ['a', 'b', 'c', 'd', 'e', 'g', '2', 'w']));

希望这有帮助,如果您有任何问题,请与我联系。

以下是documentation

的摘录
  

如果返回任何其他对象,则会以递归方式将对象字符串化为JSON字符串,并在每个属性上调用replacer函数,除非该对象是函数,在这种情况下,不会向JSON字符串添加任何内容。

对于动态键,您始终可以创建一个函数来推送到数组并将该数组用于白名单。这是一个例子:

DEMO:http://jsfiddle.net/dirtyd77/whv7x6xc/5/

var BAD = {
    "a": "2",
    "b": 1,
    "c": "Nexus",
    "d": "Alligator",
    "e": 5,
    "f": 1431807036,
    "g": {
        "2": {
            "w": 17,
            "b": 5
        }
    }
}

var whitelist = [];

iterate(BAD);

console.log(whitelist, JSON.stringify(BAD, whitelist));

function iterate(obj){
    for(var key in obj){
        // may have to do some checking to ignore any keys you don't care about
        whitelist.push(key);
        // if value is an object, will use this same function to push to whitelist array
        if(typeof obj[key] === 'object'){
            return iterate(obj[key]);
        }
    }
}

您也可以使用现有的whitelist,只需在g密钥上附加密钥(假设动态不是这样):

DEMO:http://jsfiddle.net/dirtyd77/whv7x6xc/6/

var whitelist = ['a', 'b', 'c', 'd', 'e', 'g'];

iterate(BAD.g);

console.log(whitelist, JSON.stringify(BAD, whitelist));

function iterate(obj){
    for(var key in obj){
        whitelist.push(key);
        if(typeof obj[key] === 'object'){
            return iterate(obj[key]);
        }
    }
}

答案 1 :(得分:4)

replacer参数很深,因为它会影响所有属性的字符串化,即使它们不在第一级。如果您将"2"添加到数组中,则会看到该对象已字符串化,减去"w",因为"w"未被替换者列入白名单。

JSON.stringify(BAD, ['a', 'b', 'c', 'd', 'e', 'g', '2'])

考虑使用replacer的原因。如果你使用黑名单而不是白名单,你可能会通过传入函数而不是数组来提供更好的服务。

JSON.stringify(BAD, function replacer(key, value) {
  var blacklist = ['b', 'g']
  return blacklist.indexOf(key) === -1 ? value : undefined
})

答案 2 :(得分:2)

为参数添加两个键,如:

JSON.stringify(BAD, ['a', 'b', 'c', 'd', 'e', 'g', '2', 'w'])

<强>输出

Fiddle