Збереження невизначеного, яке JSON.stringify видаляє інакше


79

Як зберегти невизначені значення при виконанні JSON.stringify (хеш)?

Ось приклад:

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

var string = JSON.stringify(hash);

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

Електронна пошта зникла з JSON.stringify.


11
JSON не має невизначеного значення. Що ти хочеш?
Слакс

4
Вам доведеться змінити значення на рядок "undefined"або, можливо, nullабо порожній рядок "". Як би ви віддали перевагу цьому?
Michael Berkowski

3
Закінчується json.org Зверніть увагу , що в стандартне значення може бути string, number, object, array, true, falseабо null. Зверніть увагу, що undefinedце не варіант.
Matt Burland

1
PS: у літералі об’єкта JS не потрібно цитувати ключі, значення яких є юридичними ідентифікаторами. Тобто{ name:"boda", email:undefined, country:"africa" }
Фрогц

8
Африка не є країною: P
Flimm

Відповіді:


117

Ви можете передати функцію замінника, 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)
Річка

9
хоча це рішення воно не вирішує проблему, оскільки не зберігає значення як невизначене, воно змінює його на null.
Пітер

3
@Peter JSON допускає лише nullзначення, undefinedзначення не визначене в стандарті JSON.
Flimm

3
@Flimm так, я знаю, але це все одно не вирішує проблему.
Пітер

2
Ви також можете зробити це з іншими невідступними значеннями, такими як функціїreturn typeof v === 'function' ? 'func' : v;
James 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)

Що робити, якщо я хочу зробити його рекурсивним?
Альмарон

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 (хеш, (k, v) => (v === невизначений)? '__Undefined': v) .replace (/ \ "__ undefined \" / g, 'undefined '), тому що ваш приклад замінить лише перший матч
Євген Фіцнер

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, яке перезаписує console.log з JSON.stringify, і втрата цих значень
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'); }
omikes

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
Довге рішення, але воно працює принаймні. (у моєму випадку я просто використовую підхід "перетворити в нульовий", оскільки він мені не потрібен, збережений-в-json as undefined)
Venryx

Чому голос проти? чи є варіант використання, де це не працює? якщо це так, будь ласка, надайте дані, щоб я міг виправити функцію!
Петро

1

Це спричинить його друк як, undefinedале це НЕПРАВИЛЬНИЙ json, але дійсний JavaScript.

var string = JSON.stringify(obj, function(k,v){return v===undefined?"::undefined::":v}, 2).replace(new RegExp("\"::undefined::\"", 'g'), "undefined");
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.