【问题标题】:Preserving undefined that JSON.stringify otherwise removes保留未定义的 JSON.stringify 否则将删除
【发布时间】:2014-12-19 20:46:48
【问题描述】:

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

这是一个例子:

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

var string = JSON.stringify(hash);

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

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

【问题讨论】:

  • JSON 没有未定义的值。你想要什么?
  • 您必须将值更改为字符串"undefined"null 或空字符串""。你会喜欢它吗?
  • 签出json.org注意标准值可以是stringnumberobjectarraytruefalsenull。请注意,undefined 不是一个选项。
  • PS:在 JS 对象字面量中,你不需要引用值是合法标识符的键。 IE。 { name:"boda", email:undefined, country:"africa" }
  • 非洲不是一个国家:P

标签: javascript json


【解决方案1】:

JSON 规范不允许 undefined 值,但允许 null 值。

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

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

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

【讨论】:

  • ES6: JSON.stringify(obj, (k, v) => v === undefined ? null : v)
  • 虽然这是一个解决方案,但它并不能解决问题,因为它不会将值保留为未定义,而是将其更改为 null。
  • @Peter JSON 只允许 null 值,在 JSON 标准中没有定义 undefined 值。
  • @Flimm 是的,我知道,但这仍然不能解决问题。
  • 您也可以使用其他不可显示的值来执行此操作,例如函数return typeof v === 'function' ? 'func' : v;
【解决方案2】:

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

简单的一个班轮:

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

【讨论】:

  • 如果我想让它递归怎么办?
  • "你可以通过改变它来保存它" ;)
  • 如果这是 API 的一部分并且您的编码风格是 if ( o.prop == undefined ) ...,那么您可以说“保留”语义,因为只有 null == undefined
【解决方案3】:

这应该可以解决问题

// 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"/g, 'undefined')

【讨论】:

  • 我相信最好用正则表达式替换: JSON.stringify(hash, (k, v) => (v === undefined) ? '__undefined' : v) .replace(/\" __undefined\"/g, 'undefined') 因为您的示例将仅替换第一个匹配项
  • +1 使用正则表达式。如果您这样做,请注意无需转义":您可以转义replace(/\"__undefined\"/g, 'undefined') 而不是replace(/"__undefined"/g, 'undefined')。或者现在你可以使用replaceAll()
  • 这段代码的问题是它不能正确处理恰好包含"__undefined" 的字符串。此外,它还会生成 JSON.parse 无法解析的无效 JSON
  • 另外,replace 只替换一次出现(除非您使用带有 /g 标志的正则表达式)
【解决方案4】:

使用null 代替undefined

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

var string = JSON.stringify(hash);

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

【讨论】:

  • 这不是在回答问题。
【解决方案5】:
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 做同样的事情。使用用 JSON.stringify 覆盖 console.log 的 repl,并丢失这些值
  • 除了undefined 之外,我还需要它来执行NaN。如果将来有其他人这样做:function customStringify(o) { return JSON.stringify(o, (k, v) => v === undefined ? '__undefined__' : v !== v ? '__NaN__' : v).replace(/"__undefined__"/g, 'undefined').replace(/"__NaN__"/g, 'NaN'); }
  • 这段代码有两个问题。首先,如果对象碰巧包含一个包含"__undefined__" 的字符串,它将无法正常工作。其次,它将无法生成可以被JSON.parse解析的有效JSON。
【解决方案6】:

我在此处的字里行间阅读并猜测您希望在使用 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"]}

【讨论】:

  • 长期解决方案,但至少可以工作。 (在我的情况下,我只是使用“转换为 null”的方法,因为我不需要它作为 undefined 保留在 json 中)
  • 为什么投反对票?是否有一个不起作用的用例?如果是这种情况,请提供数据,以便我可以更正函数!
【解决方案7】:

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

var string = JSON.stringify(obj, function(k,v){return v===undefined?"::undefined::":v}, 2).replace(new RegExp("\"::undefined::\"", 'g'), "undefined");

【讨论】:

  • 此代码的另一个问题是,如果字符串恰好包含"::undefined::",它将无法按预期工作
猜你喜欢
  • 1970-01-01
  • 2016-05-28
  • 2011-12-07
  • 1970-01-01
  • 1970-01-01
  • 2014-08-06
  • 2020-01-19
  • 1970-01-01
相关资源
最近更新 更多