Undefiniert beibehalten, das JSON.stringify ansonsten entfernt

75

Wie behalte ich undefinierte Werte bei JSON.stringify (Hash) bei?

Hier ist ein Beispiel:

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

var string = JSON.stringify(hash);

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

E-Mail verschwand aus JSON.stringify.

bodacydo
quelle
11
JSON hat keinen undefinierten Wert. Was willst du?
SLaks
4
Sie müssten den Wert in die Zeichenfolge "undefined"oder vielleicht in nulleine leere Zeichenfolge ändern "". Wie würden Sie es vorziehen?
Michael Berkowski
3
Schauen Sie sich json.org Beachten Sie, dass in dem Standardwert sein kann string, number, object, array, true, falseoder null. Beachten Sie, dass dies undefinedkeine Option ist.
Matt Burland
1
PS: In einem JS-Objektliteral müssen Sie keine Schlüssel in Anführungszeichen setzen, deren Werte zulässige Bezeichner sind. Ie{ name:"boda", email:undefined, country:"africa" }
Phrogz
8
Afrika ist kein Land: P
Flimm

Antworten:

113

Sie können eine Ersetzungsfunktion übergeben, JSON.stringifyum undefinedWerte automatisch in nullWerte wie folgt umzuwandeln :

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

Dies funktioniert auch für undefinierte Werte in Arrays, da diese JSON.stringifybereits in konvertiert werden null.

Flimm
quelle
18
ES6:JSON.stringify(obj, (k, v) => v === undefined ? null : v)
Ricka
9
Dies ist zwar eine Lösung, löst das Problem jedoch nicht, da der Wert nicht als undefiniert beibehalten wird, sondern in null geändert wird.
Peter
3
@Peter JSON erlaubt nur nullWerte, undefinedim JSON-Standard ist kein Wert definiert.
Flimm
3
@Flimm ja ich weiß aber das löst das problem immer noch nicht.
Peter
2
Sie können dies auch mit anderen nicht anzeigbaren Werten wie Funktionen tunreturn typeof v === 'function' ? 'func' : v;
James Heazlewood
8

Verwenden Sie nullanstelle von undefined.

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

var string = JSON.stringify(hash);

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

Sie können den Schlüssel beibehalten, indem Sie ihn konvertieren, nullda ein gültiger JSON dies nicht zulässt undefined.

Einfacher Einzeiler:

JSON.stringify(obj, (k, v) => v === undefined ? null : v)
Hühner
quelle
Was ist, wenn ich es rekursiv machen möchte?
Almaron
4
"Sie können es bewahren, indem Sie es ändern";)
Hatfinch
6

Dies sollte den Trick tun

// 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')
Zizaco
quelle
2
Ich glaube, es ist besser, über regulären Ausdruck zu ersetzen: JSON.stringify (Hash, (k, v) => (v === undefined)? '__Undefined': v) .replace (/ "__ undefined" / g, "undefined" ') weil Ihr Beispiel nur das erste Spiel ersetzen wird
Evgeniy Fitsner
3
function stringifyWithUndefined(obj, space) {
  const str = JSON.stringify(obj, (key, value) => value === undefined ? '__undefined__' : value, space);
  return str.replace(/"__undefined__"/g, 'undefined');
}

Beispiel:

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

Ergebnis:

{
  "name": "boda",
  "email": undefined,
  "country": "africa"
}
tanguy_k
quelle
Ich könnte dies erweitern, um dasselbe für NaN zu tun. Verwenden Sie repl, das console.log mit JSON.stringify überschreibt, und verlieren Sie diese Werte
Drenai
Ich brauchte es NaNzusätzlich dazu undefined. Für den Fall, dass es in Zukunft jemand anderes tut: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

Ich lese hier zwischen den Zeilen und vermute, dass der Wert undefiniert sein soll, wenn Sie JSON.parse verwenden?

In diesem Fall können Sie Folgendes verwenden:

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);

stringifyAndPreserveUndefinedcodiert alle undefinierten Werte in einem Array und platziert sie beim Aufrufen parseAndRestoreUndefinedwieder an der richtigen Stelle.

Der einzige Nachteil ist, dass der JSON nicht genau wie das Objekt aussieht. Im obigen Beispiel wird es in{"ROOT":{"test1":"a","test2":"b","test4":{"test1":"a"}},"undefinedPaths":["ROOT.test3","ROOT.test4.test2"]}

Peter
quelle
1
Lange Lösung, aber es funktioniert zumindest. (In meinem Fall verwende ich nur den Ansatz "In Null konvertieren", da ich ihn nicht als json erhalten habe undefined)
Venryx
Warum das Downvote? Gibt es einen Anwendungsfall, in dem dies nicht funktioniert? Wenn dies der Fall ist, geben Sie bitte die Daten an, damit ich die Funktion korrigieren kann!
Peter
1

Dies führt dazu, dass es gedruckt wird, undefinedaber dies ist UNGÜLTIG json, aber es ist gültiges JavaScript.

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