Ocultar ciertos valores en la salida de JSON.stringify ()


86

¿Es posible excluir ciertos campos para que no se incluyan en la cadena json?

Aquí hay un pseudocódigo

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

Quiero excluir privateProperty1 y privateproperty2 de aparecer en la cadena json

Entonces pensé, puedo usar la función de reemplazo de cadena

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

y en el stringify

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

Pero en jsonString todavía lo veo como

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

Me gustaría la cadena sin las propiedades privadas en ellos.



4
en lugar de devolver "none", devuelve undefined.
JoeyRobichaud

1
Vi esa pregunta y no quiero eliminar propiedades ya que afecta mi aplicación actual. Estoy tratando de guardar el objeto en un archivo y la aplicación todavía tiene el objeto en vivo, por lo que eliminar una propiedad la hará inútil. Otra opción es clonar el objeto, eliminar campos y luego secuenciar el objeto clonado.
Nilesh

1
Hey Joe, eso fue genial. Lo indefinido hizo el truco. Gracias. Actualizaré la pregunta
Nilesh

Respuestas:


101

Los documentos de Mozilla dicen que regrese undefined(en lugar 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));

Aquí hay un método de duplicación, en caso de que decida seguir esa ruta (según su comentario).

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

EDITAR - Cambié la tecla de función en la función inferior para evitar que sea confusa.


33

Otra buena solución: (requiere subrayado)

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

El beneficio de esta solución es que cualquiera que llame a JSON.stringify en x tendrá resultados correctos; no es necesario que modifique las llamadas JSON.stringify individualmente.

Versión sin subrayado:

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

Voto por este enfoque porque me parece más elegante ..
Romeo Sierra

18

Puede usar la función nativa defineProperty de Object:

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

12
Esta respuesta funciona porque el enumerablevalor de este descriptor de propiedad es falso.
Soul_Master

Nota: No funciona si los datos son una matriz y se quiere ocultar el n-ésimo elemento.
Alex Szücs

3

Manera más fácil de hacer.

  1. Cree una variable y asigne una matriz vacía. Esto hace que el objeto sea el prototipo de una matriz.
  2. Agregue claves no numéricas en este objeto.
  3. Serialice este objeto usando JSON.stringify
  4. Verá que no se serializa nada de este objeto.

~~~

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 es otra solución que se acerca a la solución defineProperty (las propiedades se definen de la misma manera) pero de esta manera se definen las propiedades a exponer desde el principio. De esta manera, puede exponer solo las propiedades que desea estableciendo el valor de la propiedad enumerableen verdadero (falso de forma predeterminada), JSON.stringify ignora las propiedades no enumerables, la desventaja es que esta propiedad también se ocultará cuando se use for-in bucle en el objeto o funciones como 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 para la respuesta de Miroslaw Dylag : La propiedad definida debe ser su propia propiedad. De lo contrario, fallaría.

No funciona:

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)

Trabajos:

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

Sé que esta ya es una pregunta respondida, pero me gustaría agregar algo al usar objetos instalados.

Si lo asigna mediante una función, no se incluirá en el resultado JSON.stringify ().

Para acceder al valor, llámelo también como una función, 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

También puede jugar con el concepto incluso cuando no esté en objetos instalados.


Esto solo funciona si no necesita establecer el valor de esa propiedad.
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

puedes hacerlo fácilmente con ES2017

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

Aquí privateProperty1y privateProperty2están asignados exc1y en exc2consecuencia. Los restantes se asignan a la foovariable recién creada



0

Aquí hay otro enfoque, aunque sin soporte para Internet Explorer.

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

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

0

Esta es una pregunta antigua, pero estoy agregando una respuesta, ya que hay una forma mucho más sencilla de abordar esto. Pase una matriz de cadenas que desea generar en 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

Aquí está mi enfoque con el operador de propagación (...):

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

const jsonWithoutId = JSON.stringify({...o, id:undefined});
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.