Ukryj określone wartości w danych wyjściowych z JSON.stringify ()


86

Czy można wykluczyć niektóre pola z ciągu JSON?

Oto pseudo kod

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

Chcę wykluczyć privateProperty1 i privateproperty2 z pojawiania się w ciągu json

Pomyślałem więc, że mogę użyć funkcji zamiennika stringify

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

i w stringify

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

Ale w jsonString nadal widzę to jako

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

Chciałbym, aby łańcuch nie zawierał w nich właściwości privateproperties.



4
zamiast zwracać „none”, zwraca undefined.
JoeyRobichaud

1
Widziałem to pytanie i nie chcę usuwać właściwości, ponieważ ma to wpływ na moją bieżącą aplikację. Próbuję zapisać obiekt w pliku, a aplikacja nadal ma obiekt na żywo, więc usunięcie właściwości spowoduje, że będzie bezużyteczna. Inną opcją jest to, że mógłbym sklonować obiekt, usunąć pola, a następnie określić klon obiektu.
Nilesh

1
Hej Joe, to było świetne. Niezdefiniowany załatwił sprawę. Dzięki. Zaktualizuję pytanie
Nilesh,

Odpowiedzi:


101

Dokumentacja Mozilli mówi, aby powrócić undefined(zamiast "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));

Oto metoda powielania, na wypadek gdybyś zdecydował się pójść tą drogą (zgodnie z twoim komentarzem).

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

EDYCJA - zmieniłem klawisz funkcyjny w dolnej funkcji, aby nie był mylący.


33

Kolejne dobre rozwiązanie: (wymaga podkreślenia)

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

Zaletą tego rozwiązania jest to, że każdy, kto wywołuje JSON.stringify na x, będzie miał poprawne wyniki - nie musisz indywidualnie zmieniać wywołań JSON.stringify.

Wersja bez podkreślenia:

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

Głosuję na takie podejście, ponieważ uważam, że jest bardziej eleganckie ...
Romeo Sierra

18

Możesz użyć natywnej funkcji defineProperty z Object:

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

12
Ta odpowiedź działa, ponieważ enumerablewartość tego deskryptora właściwości jest fałszywa.
Soul_Master

Uwaga: Nie działa, jeśli dane są tablicą i chce się ukryć n-ty jej element.
Alex Szücs

3

Łatwiejszy sposób.

  1. Utwórz zmienną i przypisz pustą tablicę. To sprawia, że ​​obiekt jest prototypem tablicy.
  2. Dodaj klucze nienumeryczne do tego obiektu.
  3. Serializuj ten obiekt przy użyciu JSON.stringify
  4. Zobaczysz, że nic nie jest serializowane z tego obiektu.

~~~

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 to kolejne rozwiązanie, które jest zbliżone do rozwiązania defineProperty (właściwości są definiowane w ten sam sposób), ale w ten sposób definiujesz właściwości, które mają być widoczne od początku. W ten sposób możesz ujawnić tylko te właściwości, które chcesz, ustawiając enumerablewartość właściwości na true (domyślnie false), JSON.stringify ignoruje niewliczalne właściwości, wadą jest to, że ta właściwość będzie również ukryta podczas używania for-in pętla na obiekcie lub funkcje, takie jak 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

Uwaga dla Mirosław Dyląg „s odpowiedź : Zdefiniowana nieruchomość powinna być jego własnością. Inaczej by się nie udało.

Nie działa:

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)

Pracuje:

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

Wiem, że jest to już pytanie, na które udzielono odpowiedzi, ale chciałbym coś dodać, gdy używam obiektów instatowanych.

Jeśli przypiszesz go za pomocą funkcji, nie zostanie uwzględniony w wyniku JSON.stringify ().

Aby uzyskać dostęp do wartości, wywołaj ją również jako funkcję, kończąc na ()

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

Możesz także bawić się tą koncepcją, nawet jeśli nie masz zainstalowanych obiektów.


Działa to tylko wtedy, gdy nie musisz ustawiać wartości tej właściwości.
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

możesz to łatwo zrobić dzięki ES2017

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

Tutaj privateProperty1i privateProperty2są przypisane do exc1i exc2odpowiednio. Reszta jest przypisywana do foonowo utworzonej zmiennej



0

Oto inne podejście, chociaż bez obsługi przeglądarki Internet Explorer.

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

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

0

To jest stare pytanie, ale dodaję odpowiedź, ponieważ istnieje znacznie prostszy sposób na rozwiązanie tego problemu. Przekaż tablicę ciągów, które chcesz wyprowadzić w formacie 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

Oto moje podejście z operatorem spreadu (...):

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

const jsonWithoutId = JSON.stringify({...o, id:undefined});
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.