保留JSON.stringify以其他方式移除的undefined

qzwqbdag  于 2023-01-27  发布在  其他
关注(0)|答案(8)|浏览(584)

执行JSON.stringify(hash)时如何保留undefined值?
下面是一个例子:

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

var string = JSON.stringify(hash);

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

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

2izufjch

2izufjch1#

function stringifyWithUndefined(value: any, space: number): string {
  const str = JSON.stringify(
    value,
    (_k, v) => v === undefined ? '__UNDEFINED__' : v,
    space
  );
  return str.replaceAll('"__UNDEFINED__"', 'undefined');
}

例一:

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

结果(字符串):

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

例二:

const array = [object, { object }, [[object]]];
console.log(stringifyWithUndefined(array, 2));

结果(字符串):

[
  {
    "name": "boda",
    "email": undefined,
    "country": "africa"
  },
  {
    "object": {
      "name": "boda",
      "email": undefined,
      "country": "africa"
    }
  },
  [
    [
      {
        "name": "boda",
        "email": undefined,
        "country": "africa"
      }
    ]
  ]
]

请注意,undefined不是有效的JSON,如果您将stringifyWithUndefined()的结果提供给它,则JSON.parse()将失败并返回SyntaxError: Unexpected token [...] is not valid JSON

p1iqtdky

p1iqtdky2#

JSON没有undefined值,但我们可以编写一个变通方案:

保留嵌套的未定义值

我编写了2个函数,它们在内部使用JSON.stringifyJSON.parse,并使用值占位符保留嵌套的undefined值:
相当于JSON.stringify

/**
 * Serialize a POJO while preserving nested `undefined` values.
 */
function serializePOJO(value, undefinedPlaceholder = "[undefined]") {
  const replacer = (key, value) => (value === undefined ? undefinedPlaceholder : value);
  return JSON.stringify(value, replacer);
}

相当于JSON.parse

/**
 * Deserialize a POJO while preserving nested `undefined` values.
 */
function deserializePOJO(value, undefinedPlaceholder = "[undefined]") {
  const pojo = JSON.parse(value);
  if (pojo === undefinedPlaceholder) {
    return undefined;
  }

  // Function that walks through nested values
  function deepIterate(value, callback, parent, key) {
    if (typeof value === "object" && value !== null) {
      Object.entries(value).forEach(([entryKey, entryValue]) => deepIterate(entryValue, callback, value, entryKey));
    } else if (Array.isArray(value)) {
      value.forEach((itemValue, itemIndex) => deepIterate(itemValue, callback, value, itemIndex));
    } else if (parent !== undefined) {
      callback(value, parent, key);
    }
  }

  // Replaces `undefined` placeholders
  deepIterate(pojo, (value, parent, key) => {
    if (value === undefinedPlaceholder) {
      parent[key] = undefined;
    }
  });

  return pojo;
}

用法:

const source = {
    foo : undefined,
  bar : {
   baz : undefined
  }
};

const serialized = serializePOJO(source);
console.log("Serialized", serialized);
// '{"foo":"[undefined]","bar":{"baz":"[undefined]","qux":[1,"[undefined]",2]}}'

const deserialized = deserializePOJO(serialized);
console.log("Deserialized", deserialized);

可用于对象项和数组项。
缺点是你必须选择一个合适的占位符,它不会被"真实的"源代码值弄错,占位符可以通过可选的undefinedPlaceholder参数定制。
这对于在浏览器local storage中存储POJO特别有用;)
另见:

wgxvkvu9

wgxvkvu93#

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

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

vx6bjr1n4#

JSON规范不允许undefined值,但允许null值。
您可以将replacer函数传递给JSON.stringify,以自动将undefined值转换为null值,如下所示:

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

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

bbuxkriu

bbuxkriu5#

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

简单的一行:

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

myzjeezk6#

这个应该可以

// 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')
jc3wubiy

jc3wubiy7#

使用null代替undefined

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

var string = JSON.stringify(hash);

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

a2mppw5e8#

我正在阅读这里的字里行间,猜想您希望在使用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"]}

相关问题