Masquer certaines valeurs dans la sortie de JSON.stringify ()

86

Est-il possible d'exclure certains champs de l'inclusion dans la chaîne json?

Voici un pseudo code

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

Je veux exclure privateProperty1 et privateproperty2 d'apparaître dans la chaîne json

Alors j'ai pensé, je peux utiliser la fonction de remplacement stringify

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

et dans le stringify

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

Mais dans le jsonString, je le vois toujours comme

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

Je voudrais la chaîne sans les propriétés privées en eux.

Nilesh
la source
Double possible: stackoverflow.com/questions/208105/…
Jared Farrish
4
au lieu de renvoyer «aucun», retourne undefined.
JoeyRobichaud
1
J'ai vu cette question et je ne veux pas supprimer les propriétés car cela affecte mon application actuelle. J'essaie d'enregistrer l'objet dans un fichier et l'application a toujours l'objet en direct, donc la suppression d'une propriété la rendra inutile. Une autre option est que je pourrais cloner l'objet, supprimer des champs, puis stringifier l'objet clone.
Nilesh le
1
Hé Joe, c'était super. L'indéfini a fait l'affaire. Merci. Je vais mettre à jour la question
Nilesh

Réponses:

101

Les documents de Mozilla disent de retourner undefined(au lieu de "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));

Voici une méthode de duplication, au cas où vous décidez d'emprunter cette voie (selon votre commentaire).

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 - J'ai changé la touche de fonction dans la fonction du bas pour éviter qu'elle ne prête à confusion.

Jared Farrish
la source
33

Une autre bonne solution: (nécessite un trait de soulignement)

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

L'avantage de cette solution est que toute personne appelant JSON.stringify sur x obtiendra des résultats corrects - vous n'avez pas à modifier les appels JSON.stringify individuellement.

Version sans trait de soulignement:

x.toJSON = function () {
    var result = {};
    for (var x in this) {
        if (x !== "privateProperty1" && x !== "privateProperty2") {
            result[x] = this[x];
        }
    }
    return result;
};
Curtis Yallop
la source
Je vote pour cette approche parce que je la trouve plus élégante ..
Romeo Sierra
18

Vous pouvez utiliser la fonction native defineProperty depuis Object:

var data = {a: 10};
Object.defineProperty(data, 'transient', {value: 'static', writable: true});
data.transient = 'dasda';
console.log(JSON.stringify(data)); //{"a":10}
Miroslaw Dylag
la source
12
Cette réponse fonctionne car la enumerablevaleur de ce descripteur de propriété est fausse.
Soul_Master
Remarque: cela ne fonctionne pas si les données sont un tableau et que l'on veut en cacher le n-ième élément.
Alex Szücs
3

Manière plus simple de faire.

  1. Créez une variable et assignez un tableau vide. Cela fait de l'objet le prototype du tableau.
  2. Ajoutez des clés non numériques sur cet objet.
  3. Sérialisez cet objet à l'aide de JSON.stringify
  4. Vous verrez que rien n'est sérialisé à partir de cet objet.

~~~

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

Markandey Singh
la source
2

Object.create est une autre solution proche de la solution defineProperty (les propriétés sont définies de la même manière) mais vous définissez ainsi les propriétés à exposer depuis le début. De cette façon, vous pouvez exposer uniquement les propriétés que vous souhaitez en définissant la enumerablevaleur de la propriété sur true (false par défaut), JSON.stringify ignore les propriétés non énumérables, l'inconvénient est que cette propriété sera également masquée lors de l'utilisation de for-in boucle sur l'objet ou des fonctions comme 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"}"
Matan Hafuta
la source
2

Note pour Miroslaw Dylag de réponse : La propriété définie doit être sa propre propriété. Sinon, cela échouerait.

Ne fonctionne pas:

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)

Travaux:

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)
Audi Nugraha
la source
1

Je sais que c'est déjà une question avec réponse, mais j'aimerais ajouter quelque chose lors de l'utilisation d'objets instatiés.

Si vous l'affectez à l'aide d'une fonction, il ne sera pas inclus dans le résultat JSON.stringify ().

Pour accéder à la valeur, appelez-la également en tant que fonction, en terminant par ()

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

Vous pouvez également jouer avec le concept même lorsque vous n'êtes pas sur des objets installés.

dragonjet
la source
Cela ne fonctionne que si vous n'avez pas besoin de définir la valeur de cette propriété.
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;
    };
}
Carlos Arturo Alaniz
la source
0

vous pouvez le faire facilement avec ES2017

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

Ici privateProperty1et privateProperty2sont affectés à exc1et en exc2conséquence. Les restes sont affectés à la foovariable nouvellement créée

peja
la source
0

Voici une autre approche, bien que sans le support d'Internet Explorer.

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

const jsonString = JSON.stringify(x, excludePrivateProperties);
Mike Nikles
la source
0

C'est une vieille question, mais j'ajoute une réponse car il existe un moyen beaucoup plus simple de traiter cela. Passez un tableau de chaînes que vous souhaitez générer dans le 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"}

delp
la source
0

Voici mon approche avec l'opérateur de diffusion (...):

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

const jsonWithoutId = JSON.stringify({...o, id:undefined});
Reinhard
la source