Приховати певні значення у вихідних даних із JSON.stringify ()


86

Чи можна виключити певні поля із включення в рядок json?

Ось якийсь псевдокод

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

Я хочу виключити privateProperty1 і privateproperty2 від появи в рядку json

Тож я подумав, що можу скористатися функцією заміни stringify

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

і в stringify

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

Але в jsonString я все ще бачу це як

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

Я хотів би, щоб рядок без приватних властивостей у них.



4
замість повернення "none" повертається невизначеним.
JoeyRobichaud

1
Я побачив це запитання, і я не хочу видаляти властивості, оскільки це впливає на мою поточну програму. Я намагаюся зберегти об'єкт у файл, і програма все ще має активний об'єкт, тому видалення властивості зробить його марним. Іншим варіантом є те, що я міг клонувати об’єкт, видаляти поля, а потім об'єднувати клонування.
Нілеш

1
Ей Джо, це було чудово. Невизначені зробили свою справу. Дякую. Я
оновлю

Відповіді:


101

Документи Mozilla говорять повернути undefined(замість "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));

Ось метод дублювання, якщо ви вирішите піти цим шляхом (згідно з вашим коментарем).

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

РЕДАГУВАТИ - Я змінив функціональну клавішу в нижній функції, щоб не заплутувати.


33

Ще одне хороше рішення: (потрібно підкреслення)

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

Перевага цього рішення полягає в тому, що кожен, хто викликає JSON.stringify на x, матиме правильні результати - вам не потрібно змінювати виклики JSON.stringify окремо.

Версія без підкреслення:

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

Я голосую за такий підхід, тому що вважаю його більш елегантним ..
Ромео Сьєрра,

18

Ви можете використовувати власну функцію defineProperty з Object:

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

12
Ця відповідь працює, оскільки enumerableзначення цього дескриптора властивостей хибне.
Soul_Master

Примітка: Це не працює, якщо дані є масивом, і хочеться приховати n-й його елемент.
Алекс Шуц

3

Це простіше зробити.

  1. Створіть змінну та призначте порожній масив. Це робить об’єкт прототипом масиву.
  2. Додайте нечислові клавіші до цього об’єкта.
  3. Серіалізуйте цей об’єкт за допомогою JSON.stringify
  4. Ви побачите, що з цього об’єкта нічого не серіалізовано.

~~~

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 - це ще одне рішення, близьке до рішення defineProperty (властивості визначаються однаково), але таким чином ви визначаєте властивості, які потрібно виставляти з самого початку. Таким чином ви можете виставити лише ті властивості, які хочете, встановивши для enumerableзначення властивості значення true (за замовчуванням false), JSON.stringify ігнорує неперелічені властивості, недоліком є ​​те, що ця властивість буде також прихована при використанні for-in цикл на об'єкті або такі функції, як 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

Зверніть увагу на Мирослав Dylag «s відповіді : Задана власність повинна бути його власністю. Інакше це не вдалося б.

Не працює:

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)

Твори:

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

Я знаю, що це вже відповідь на запитання, але я хотів би щось додати при використанні інстанованих об’єктів.

Якщо ви призначите його за допомогою функції, вона не буде включена в результат JSON.stringify ().

Щоб отримати доступ до значення, також викличте його як функцію, що закінчується на ()

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

Ви також можете пограти з концепцією, навіть коли не на нестаціонарних об'єктах.


Це працює, лише якщо вам не потрібно встановлювати значення цієї властивості.
Габріель С

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

Ви можете легко це зробити за допомогою ES2017

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

Тут privateProperty1і privateProperty2присвоюються exc1і exc2відповідно. Залишки присвоюються fooновоствореній змінній



0

Ось інший підхід, хоча без підтримки Internet Explorer.

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

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

0

Це старе запитання, але я додаю відповідь, оскільки є набагато простіший спосіб вирішити це. Передайте масив рядків, які ви хочете вивести в 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

Ось мій підхід до оператора поширення (...):

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

const jsonWithoutId = JSON.stringify({...o, id:undefined});
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.