保留undefined,否则JSON.stringify会删除


79

在执行JSON.stringify(hash)时如何保留未定义的值?

这是一个例子:

var hash = {
  "name" : "boda",
  "email" : undefined,
  "country" : "africa"
};

var string = JSON.stringify(hash);

> "{"name":"boda","country":"africa"}"

电子邮件从JSON.stringify中消失了。


11
JSON没有未定义的值。你想要什么?
SLaks

4
您将不得不将值更改为字符串,"undefined"或者也许是null一个空字符串""。您会如何选择它?
Michael Berkowski

3
退房json.org注意的是,在标准值可以是stringnumberobjectarraytruefalsenull。请注意,这undefined不是一个选择。
马特·伯兰

1
PS:在JS对象文字中,您不需要引用其值为合法标识符的键。即{ name:"boda", email:undefined, country:"africa" }
-Phrogz

8
非洲不是一个国家:P
Flimm '18

Answers:


117

您可以传递一个replacer函数来JSON.stringify自动将undefined值转换为null值,如下所示:

var string = JSON.stringify(
  obj,
  function(k, v) { return v === undefined ? null : v; }
);

这也适用于数组内的未定义值,因为JSON.stringify已经将它们转换为null


18
ES6:JSON.stringify(obj, (k, v) => v === undefined ? null : v)
ricka

9
尽管这是一个解决方案,但它不能解决问题,因为它不会将值保留为未定义,而是将其更改为null。
彼得

3
@Peter JSON仅允许null值,undefinedJSON标准中未定义任何值。
Flimm

3
@Flimm是的,我知道,但这仍然不能解决问题。
彼得

2
您还可以与其他不可显示的值,如功能做到这一点return typeof v === 'function' ? 'func' : v;
詹姆斯Heazlewood

8

使用null代替undefined

var hash = {
  "name" : "boda",
  "email" : null,
  "country" : "africa"
};

var string = JSON.stringify(hash);

> "{"name":"boda","email":null,"country":"africa"}"

7

您可以通过转换为来保留密钥,null因为有效的JSON不允许undefined

简单的一个班轮:

JSON.stringify(obj, (k, v) => v === undefined ? null : v)

如果我想使其递归怎么办?
Almaron

4
“您可以通过更改来保存它”;)
hatfinch

6

这应该可以解决问题

// Since 'JSON.stringify' hides 'undefined', the code bellow is necessary in
// order to display the real param that have invoked the error.
JSON.stringify(hash, (k, v) => (v === undefined) ? '__undefined' : v)
    .replace('"__undefined"', 'undefined')

2
我认为最好用正则表达式替换:JSON.stringify(hash,(k,v)=>(v === undefined)?'__undefined':v).replace(/ \“ __ undefined \” / g,'undefined '),因为您的示例将仅替换第一个比赛
Evgeniy Fitsner '19

3
function stringifyWithUndefined(obj, space) {
  const str = JSON.stringify(obj, (key, value) => value === undefined ? '__undefined__' : value, space);
  return str.replace(/"__undefined__"/g, 'undefined');
}

例:

const obj = {
  name: 'boda',
  email: undefined,
  country: 'africa'
};
console.log(stringifyWithUndefined(obj, 2));

结果:

{
  "name": "boda",
  "email": undefined,
  "country": "africa"
}

我可以将其扩展为对NaN执行相同的操作。使用repl使用JSON.stringify覆盖console.log,并丢失这些值
Drenai

我需要它做的NaN除了undefined为好。如果将来有其他人这样做:function customStringify(o) { return JSON.stringify(o, (k, v) => v === undefined ? '__undefined__' : v !== v ? '__NaN__' : v).replace(/"__undefined__"/g, 'undefined').replace(/"__NaN__"/g, 'NaN'); }
忽略

2

我在这里读到两行之间,并猜测您想要在使用JSON.parse时具有未定义的值吗?

如果是这样,您可以使用以下方法:

var encodeUndefined = function(obj, undefinedPaths, path) {
  path = path || 'ROOT';
  for (var key in obj) {
    var keyPath = path + '.' + key;
    var value = obj[key];
    if (value === undefined) {
      undefinedPaths.push(keyPath);
    } else if (typeof value == "object" && value !== null) {
      encodeUndefined(obj[key], undefinedPaths, keyPath);
    }
  }
}

var stringifyAndPreserveUndefined = function(obj) {
  var undefinedPaths = [];
  //save all paths that have are undefined in a array.
  encodeUndefined((obj), undefinedPaths);
  return JSON.stringify({
    ROOT: obj,
    undefinedPaths: undefinedPaths
  }, function(k, v) { if (v === undefined) { return null; } return v; });
}

var parseAndRestoreUndefined = function(value) {
  var data = JSON.parse(value);
  var undefinedPaths = data.undefinedPaths;
  var obj = data.ROOT;
  //Restore all undefined values
  for (var pathIndex = 0; pathIndex < undefinedPaths.length; pathIndex++) {
    var pathParts = undefinedPaths[pathIndex].substring(5).split('.');
    var item = obj;
    for (var pathPartIndex = 0; pathPartIndex < pathParts.length - 1; pathPartIndex++) {
      item = item[pathParts[pathPartIndex]];
    }
    item[pathParts[pathParts.length - 1]] = undefined;
  }
  return obj;
}

var input = {
  test1: 'a',
  test2: 'b',
  test3: undefined,
  test4: {
    test1: 'a',
    test2: undefined
  }
};
var result = stringifyAndPreserveUndefined(input);
var result2 = parseAndRestoreUndefined(result);

stringifyAndPreserveUndefined将所有未定义的值编码在数组中,当您调用parseAndRestoreUndefined它时,会将它们再次放置在正确的位置。

不利的一面是json看起来不会完全像对象。在上面的示例中,它将变成{"ROOT":{"test1":"a","test2":"b","test4":{"test1":"a"}},"undefinedPaths":["ROOT.test3","ROOT.test4.test2"]}


1
长期解决方案,但至少有效。(就我而言,我只使用“转换为null”方法,因为我不需要将它保存为json undefined
Venryx

为什么要投票?有没有用的案例?如果是这种情况,请提供数据,以便我可以更正功能!
彼得,

1

这将导致它打印为,undefined但这是INVALID json,但是是有效的JavaScript。

var string = JSON.stringify(obj, function(k,v){return v===undefined?"::undefined::":v}, 2).replace(new RegExp("\"::undefined::\"", 'g'), "undefined");
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.