Nascondi determinati valori nell'output di JSON.stringify ()


86

È possibile escludere determinati campi dall'inclusione nella stringa json?

Ecco alcuni pseudo codice

var x = {
    x:0,
    y:0,
    divID:"xyz",
    privateProperty1: 'foo',
    privateProperty2: 'bar'
}

Voglio escludere privateProperty1 e privateproperty2 dalla visualizzazione nella stringa json

Quindi ho pensato, posso usare la funzione di sostituzione stringify

function replacer(key,value)
{
    if (key=="privateProperty1") then retun "none";
    else if (key=="privateProperty2") then retun "none";
    else return value;
}

e nel stringify

var jsonString = json.stringify(x,replacer);

Ma in jsonString lo vedo ancora come

{...privateProperty1:value..., privateProperty2:value }

Vorrei la stringa senza le proprietà private in esse.



4
invece di restituire "nessuno" restituisce undefined.
JoeyRobichaud

1
Ho visto questa domanda e non voglio eliminare le proprietà poiché influisce sulla mia applicazione corrente. Sto cercando di salvare l'oggetto in un file e l'applicazione ha ancora l'oggetto live, quindi l'eliminazione di una proprietà lo renderà inutile. Un'altra opzione è che potrei clonare l'oggetto, eliminare i campi e quindi stringere l'oggetto clone.
Nilesh

1
Ehi Joe, è stato fantastico. L'indefinito ha fatto il trucco. Grazie. Aggiornerò la domanda
Nilesh

Risposte:


100

I documenti di Mozilla dicono di tornare undefined(invece di "none"):

http://jsfiddle.net/userdude/rZ5Px/

function replacer(key,value)
{
    if (key=="privateProperty1") return undefined;
    else if (key=="privateProperty2") return undefined;
    else return value;
}

var x = {
    x:0,
    y:0,
    divID:"xyz",
    privateProperty1: 'foo',
    privateProperty2: 'bar'
};

alert(JSON.stringify(x, replacer));

Ecco un metodo di duplicazione, nel caso in cui decidi di seguire quella strada (come da tuo commento).

http://jsfiddle.net/userdude/644sJ/

function omitKeys(obj, keys)
{
    var dup = {};
    for (var key in obj) {
        if (keys.indexOf(key) == -1) {
            dup[key] = obj[key];
        }
    }
    return dup;
}

var x = {
    x:0,
    y:0,
    divID:"xyz",
    privateProperty1: 'foo',
    privateProperty2: 'bar'
};

alert(JSON.stringify(omitKeys(x, ['privateProperty1','privateProperty2'])));

EDIT - Ho cambiato il tasto funzione nella funzione in basso per evitare che sia confuso.


33

Un'altra buona soluzione: (richiede il trattino basso)

x.toJSON = function () {
    return _.omit(this, [ "privateProperty1", "privateProperty2" ]);
};

Il vantaggio di questa soluzione è che chiunque chiami JSON.stringify su x avrà risultati corretti: non è necessario modificare le chiamate JSON.stringify individualmente.

Versione senza trattino basso:

x.toJSON = function () {
    var result = {};
    for (var x in this) {
        if (x !== "privateProperty1" && x !== "privateProperty2") {
            result[x] = this[x];
        }
    }
    return result;
};

Voto per questo approccio perché lo trovo più elegante ..
Romeo Sierra

18

È possibile utilizzare la funzione nativa defineProperty da Object:

var data = {a: 10};
Object.defineProperty(data, 'transient', {value: 'static', writable: true});
data.transient = 'dasda';
console.log(JSON.stringify(data)); //{"a":10}

12
Questa risposta funziona perché il enumerablevalore di questo descrittore di proprietà è falso.
Soul_Master

Nota: non funziona se i dati sono un array e si desidera nascondere l'elemento n-esimo di esso.
Alex Szücs,

3

Modo più semplice per farlo.

  1. Crea una variabile e assegna un array vuoto. Questo fa sì che object sia il prototipo di array.
  2. Aggiungi chiavi non numeriche su questo oggetto.
  3. Serializza questo oggetto utilizzando JSON.stringify
  4. Vedrai che nulla è serializzato da questo oggetto.

~~~

var myobject={
  a:10,
  b:[]
};

myobject.b.hidden1 = 'hiddenValue1';
myobject.b.hidden2 = 'hiddenValue2';

//output of stringify 
//{
//    "a": 10,
//    "b": []
//}

~~~

http://www.markandey.com/2015/07/how-to-hide-few-keys-from-being-being.html


2

Object.create è un'altra soluzione che è vicina alla soluzione defineProperty (le proprietà sono definite allo stesso modo) ma in questo modo si definiscono le proprietà da esporre dall'inizio. In questo modo puoi esporre solo le proprietà che desideri impostando il enumerablevalore della proprietà su true (false per impostazione predefinita), JSON.stringify ignora le proprietà non enumerabili, lo svantaggio è che anche questa proprietà verrà nascosta quando si utilizza for-in loop sull'oggetto o funzioni come Object.keys.

var x = Object.create(null, {
    x: {value:0, enumerable: true}, 
    y:{value: 0, enumerable: true}, 
    divID: {value: 'xyz', enumerable: true}, 
    privateProperty1: {value: 'foo'}, 
    privateProperty2: {value: 'bar'}
});
JSON.stringify(x)
//"{"x":0,"y":0,"divID":"xyz"}"

2

Nota per la risposta di Miroslaw Dylag : la proprietà definita dovrebbe essere di sua proprietà. Altrimenti fallirebbe.

Non funziona:

class Foo {
}
Object.defineProperty(Foo.prototype, 'bar', { value: 'bar', writable: true });

const foo = new Foo();
foo.bar = 'baz';
alert(JSON.stringify(foo).indexOf('bar') === -1); // false (found)

Lavori:

class Foo {
  constructor() {
    Object.defineProperty(this, 'bar', { value: 'bar', writable: true });
  }
}

const foo = new Foo();
foo.bar = 'baz';
alert(JSON.stringify(foo).indexOf('bar') === -1); // true (not found)

1

So che questa è già una domanda con risposta, ma vorrei aggiungere qualcosa quando si utilizzano oggetti istanziati.

Se lo assegni utilizzando una funzione, non verrà incluso nel risultato JSON.stringify ().

Per accedere al valore, chiamalo anche come funzione, terminando con ()

var MyClass = function(){
    this.visibleProperty1 = "sample1";
    this.hiddenProperty1 = function(){ return "sample2" };
}

MyClass.prototype.assignAnother = function(){
    this.visibleProperty2 = "sample3";
    this.visibleProperty3 = "sample4";
    this.hiddenProperty2 = function(){ return "sample5" };
}

var newObj = new MyClass();
console.log( JSON.stringify(newObj) );
// {"visibleProperty1":"sample1"}

newObj.assignAnother();
console.log( JSON.stringify(newObj) );
// {"visibleProperty1":"sample1","visibleProperty2":"sample3","visibleProperty3":"sample4"}

console.log( newObj.visibleProperty2 ); // sample3
console.log( newObj.hiddenProperty1() ); // sample2
console.log( newObj.hiddenProperty2() ); // sample5

Puoi anche giocare con il concetto anche quando non su oggetti istanziati.


Funziona solo se non è necessario impostare il valore di quella proprietà.
Gabriel C

0
abstract class Hideable {
    public hidden = [];
    public toJSON() {
        var result = {};
        for (var x in this) {
            if(x == "hidden") continue;
            if (this.hidden.indexOf(x) === -1) {
                result[x] = this[x];
            }
        }
        return result;
    };
}

0

puoi farlo facilmente con ES2017

let {privateProperty1:exc1, privateProperty2:exc2, ...foo} = {
    x:0,
    y:0,
    divID:"xyz",
    privateProperty1: 'foo',
    privateProperty2: 'bar'
}

Qui privateProperty1e privateProperty2sono assegnati a exc1e di exc2conseguenza. I rimanenti vengono assegnati alla foovariabile appena creata



0

Ecco un altro approccio, anche se senza il supporto di Internet Explorer.

const privateProperties = ["privateProperty1", "privateProperty2"];
const excludePrivateProperties = (key, value) => privateProperties.includes(key) ? undefined : value;

const jsonString = JSON.stringify(x, excludePrivateProperties);

0

Questa è una vecchia domanda, ma aggiungo una risposta poiché esiste un modo molto più semplice per affrontarla. Passa un array di stringhe che desideri generare in JSON.

var x = {
    x:0,
    y:0,
    divID:"xyz",
    privateProperty1: 'foo',
    privateProperty2: 'bar'
}

JSON.stringify(x, ["x", "y", "divID"]);

// This will output only x y and divID
// {"x":0,"y":0,"divID":"xyz"}


0

Ecco il mio approccio con l'operatore spread (...):

const obj = { name:"hello", age:42, id:"3942" };
const objWithoutId = { ...o, id: undefined }

const jsonWithoutId = JSON.stringify({...o, id:undefined});
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.