Скрыть определенные значения в выводе 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;
}

и в строке

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

Но в jsonString я все еще вижу это как

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

Я хотел бы, чтобы строка без личных свойств в них.

Нилеш
источник
Возможный дубликат: stackoverflow.com/questions/208105/…
Джаред Фарриш
4
вместо возврата «none» верните undefined.
JoeyRobichaud 06
1
Я видел этот вопрос и не хочу удалять свойства, поскольку это влияет на мое текущее приложение. Я пытаюсь сохранить объект в файл, а в приложении все еще есть живой объект, поэтому удаление свойства сделает его бесполезным. Другой вариант - я могу клонировать объект, удалить поля, а затем преобразовать объект клонирования в строку.
Nilesh 06
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;
};
Кертис Яллоп
источник
Я голосую за этот подход, потому что считаю его более элегантным ..
Romeo Sierra
18

Вы можете использовать встроенную функцию defineProperty из объекта:

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-й элемент в нем.
Alex Szücs,
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)
Audi Nugraha
источник
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

Вы также можете поэкспериментировать с концепцией, даже если не используете отдельные объекты.

драконий самолет
источник
Это работает, только если вам не нужно устанавливать значение этого свойства.
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

вы можете легко сделать это с 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"}

delp
источник
0

Вот мой подход с оператором распространения (...):

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

const jsonWithoutId = JSON.stringify({...o, id:undefined});
Рейнхард
источник