Скрыть определенные значения в выводе из JSON.stringify()
Можно ли исключить определенные поля из включения в строку 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 }
Я хотел бы строку без частных свойств в них.
16 ответов
Документы 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'])));
РЕДАКТИРОВАТЬ - Я изменил функциональную клавишу в нижней функции, чтобы избежать путаницы.
Еще одно хорошее решение: (требует подчеркнуть)
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;
};
Вы можете использовать встроенную функцию defineProperty из Object:
var data = {a: 10};
Object.defineProperty(data, 'transient', {value: 'static', writable: true});
data.transient = 'dasda';
console.log(JSON.stringify(data)); //{"a":10}
Это старый вопрос, но я добавляю ответ, так как есть гораздо более простой способ справиться с этим. Передайте массив строк, которые вы хотите вывести в формате 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"}
Вот мой подход к оператору распространения (...):
const obj = { name:"hello", age:42, id:"3942" };
const objWithoutId = { ...o, id: undefined }
const jsonWithoutId = JSON.stringify({...o, id:undefined});
Более простой способ сделать.
- Создайте переменную и назначьте пустой массив. Это делает объект прототипом массива.
- Добавьте нечисловые ключи к этому объекту.
- Сериализация этого объекта с использованием JSON.stringify
- Вы увидите, что ничего не сериализовано из этого объекта.
~~~
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
Object.create - это другое решение, близкое к решению defineProperty (свойства определяются аналогичным образом), но таким образом вы определяете свойства, которые будут предоставлены с самого начала. Таким образом, вы можете выставить только те свойства, которые вам нужны, установив свойство enumerable
значение true (по умолчанию false), JSON.stringify игнорирует неперечислимые свойства, недостатком является то, что это свойство также будет скрыто при использовании цикла for для объекта или таких функций, как 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"}"
Примечание для Miroslaw Dylag: определенное свойство должно быть его собственным свойством. Иначе это не получится.
Не работает:
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)
Я знаю, что это уже ответ на вопрос, но я хотел бы добавить кое-что при использовании объектов на основе.
Если вы назначите его с помощью функции, он не будет включен в результат 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
Вы также можете поиграть с концепцией, даже если не на объектах.
Вот другой подход, но без поддержки Internet Explorer.
const privateProperties = ["privateProperty1", "privateProperty2"];
const excludePrivateProperties = (key, value) => privateProperties.includes(key) ? undefined : value;
const jsonString = JSON.stringify(x, excludePrivateProperties);
removes
представляет собой массив ключей, которые вы хотите опустить.
space
не является обязательным для красивой печати.
// typescript version
export function toJson<T>(me: T, removes?: (keyof T)[], space?: number): string {
return JSON.stringify(me, (k, v) => (removes?.some((r) => r === k) ? undefined : v), space);
}
// javascript version
export function toJson(me , removes , space) {
return JSON.stringify(me, (k, v) => (removes?.some((r) => r === k) ? undefined : v), space);
}
пример
const data = {name: "ali" ,age: "80"};
console.log(toJson(data, ["age"]))
// output: {"name":"ali"}
Вы можете сделать это легко с ES6
let {privateProperty1:exc1, privateProperty2:exc2, ...foo} = {
x:0,
y:0,
divID:"xyz",
privateProperty1: 'foo',
privateProperty2: 'bar'
}
Вот privateProperty1
а также privateProperty2
назначены на exc1
а также exc2
соответственно. Остальные назначены foo
вновь созданная переменная
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;
};
}
Я подписываюсь на тему delp /questions/33629298/skryit-opredelennyie-znacheniya-v-vyivode-iz-jsonstringify/55111233#55111233 Эта тема помогла с моим кодом
JSON.stringify(GetMyContent[i], ["mdlPageName", "mdlAligen", "mdlOrderNumberHorizontal", "mdlPageId", "mdlOrderNumberVertical"])
Таким образом я могу выбрать нужные мне атрибуты:
if (GetMyContent[i].mdlAligen == "Left") {
var getrownum = GetMyContent[i].mdlOrderNumberHorizontal;
if ($('.Left div.row:eq(' + (getrownum - 1) + ')').children().length > 0) {
$('.Left div.row:eq(' + (getrownum - 1) + ')').append("<div id=" + GetMyContent[i].mdlPageId + " class=\"border border-secondary col\" " + "data-atrrib=" + JSON.stringify(GetMyContent[i], ["mdlPageName", "mdlAligen", "mdlOrderNumberHorizontal", "mdlPageId", "mdlOrderNumberVertical"]) + ">" + GetMyContent[i].mdlPageContentHtml + buttonEDI + "</div>");
}
else {
$('.Left div.row:last').html("<div id=" + GetMyContent[i].mdlPageId + " class=\"border border-secondary col\" " + "data-atrrib=" + JSON.stringify(GetMyContent[i], ["mdlPageName", "mdlAligen", "mdlOrderNumberHorizontal", "mdlPageId", "mdlOrderNumberVertical"]) + ">" + GetMyContent[i].mdlPageContentHtml + buttonEDI + "</div>");
$(".Left .row:last").after($('.Left .row:eq(0)').clone().html(""));
}
}
Я использовал решение toJSON, основанное на небольшой библиотеке, которую я написал, чтобы набирать текст во время выполнения https://stackru.com/a/55917109/4236151
Помимо toJSON и заменителей. Простым решением было бы преобразовать переменную в «статическую» переменную. Поскольку статические переменные добавляются как переменные прототипа, они не будут включены в строку JSON.
Внимание: используйте это, если переменная может быть статической.