Hide certain values in output from JSON.stringify()

JavascriptJson

Javascript Problem Overview


Is it possible to exclude certain fields from being included in the json string?

Here is some pseudo code

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

I want to exclude privateProperty1 and privateproperty2 from appearing in the json string

So I thought, I can use the stringify replacer function

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

and in the stringify

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

But in the jsonString I still see it as

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

I would like to the string without the privateproperties in them.

Javascript Solutions


Solution 1 - Javascript

The Mozilla docs say to return undefined (instead of "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));

Here is a duplication method, in case you decide to go that route (as per your comment).

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

EDIT - I changed the function key in the bottom function to keep it from being confusing.

Solution 2 - Javascript

Another good solution: (requires underscore)

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

The benefit of this solution is that anyone calling JSON.stringify on x will have correct results - you don't have to alter the JSON.stringify calls individually.

Non-underscore version:

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

Solution 3 - Javascript

You can use native function defineProperty from Object:

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

Solution 4 - Javascript

This is an old question, but I'm adding an answer as there is a much simpler way to deal with this. Pass an array of strings that you wish to output in the 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"}

Solution 5 - Javascript

Here is my approach with the spread operator (...) :

const obj = {
  name: "hello",
  age: 42,
  id: "3942"
};

const objWithoutId = { ...obj, id: undefined };

const jsonWithoutId = JSON.stringify(objWithoutId);

console.log(jsonWithoutId);

Solution 6 - Javascript

Easier way to do.

  1. Create a variable and assign an empty array. This makes object to be the prototype of array.
  2. Add non numeric keys on this object.
  3. Serialize this object using JSON.stringify
  4. You will see that nothing is serialized from this object.

    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

Solution 7 - Javascript

Object.create is another solution that is close to the defineProperty solution (properties are defined in the same way) but in this way you define the properties to expose from the beginning. In this way you can expose only the properties that you want by setting the property enumerable value to true (false by default), JSON.stringify is ignoring non-enumerable properties, the downside is that this property will also be hidden when using for-in loop on the object or functions like 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"}"

Solution 8 - Javascript

Note for Miroslaw Dylag's answer: The defined property should be its own property. Otherwise it would fail.

Doesn't work:

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)

Works:

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)

Solution 9 - Javascript

I know this is already an answered question, but I'd like to add something when using instatiated objects.

If you assign it using a function, it will not be included on the JSON.stringify() result.

To access the value, call it as a function as well, ending with ()

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

You can also play around with the concept even when not on instatiated objects.

Solution 10 - Javascript

Here's another approach, although without Internet Explorer support.

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

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

Solution 11 - Javascript

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;
    };
}

Solution 12 - Javascript

you can do it easily with ES2017

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

Here privateProperty1 and privateProperty2 are assigned to exc1 and exc2 accordingly. The remainings are assigned to foo newly created variable

Solution 13 - Javascript

I've used toJSON solution based on a small library that i've written in order to get Typing at Runtime https://stackoverflow.com/a/55917109/4236151

Solution 14 - Javascript

I subscribe to delp's Topic https://stackoverflow.com/a/62457745/14491024 This topic helped with my code

 JSON.stringify(GetMyContent[i], ["mdlPageName", "mdlAligen", "mdlOrderNumberHorizontal", "mdlPageId", "mdlOrderNumberVertical"])

That way I can pick attributes that I need:

    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(""));
        }
    }

Solution 15 - Javascript

In addition to toJSON and replacers. A simple fix would be to convert the variable to a 'static' variable. Since the static variables are added as prototype variables they won't come in the JSON string.

Caution: Please use this if the variable can be a static variable.

Solution 16 - Javascript

removes is an array of keys you want to omit. space is optional for pretty printing.

// 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);
}

example

const data = {name: "ali" ,age: "80"};
console.log(toJson(data, ["age"]))

// output: {"name":"ali"}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionNileshView Question on Stackoverflow
Solution 1 - JavascriptJared FarrishView Answer on Stackoverflow
Solution 2 - JavascriptCurtis YallopView Answer on Stackoverflow
Solution 3 - JavascriptMiroslaw DylagView Answer on Stackoverflow
Solution 4 - JavascriptdelpView Answer on Stackoverflow
Solution 5 - JavascriptReinhardView Answer on Stackoverflow
Solution 6 - JavascriptMarkandey SinghView Answer on Stackoverflow
Solution 7 - JavascriptMatan HafutaView Answer on Stackoverflow
Solution 8 - JavascriptAudi NugrahaView Answer on Stackoverflow
Solution 9 - JavascriptdragonjetView Answer on Stackoverflow
Solution 10 - JavascriptMike NiklesView Answer on Stackoverflow
Solution 11 - JavascriptCarlos Arturo AlanizView Answer on Stackoverflow
Solution 12 - JavascriptpejaView Answer on Stackoverflow
Solution 13 - JavascriptYacineView Answer on Stackoverflow
Solution 14 - JavascriptMikeRyzView Answer on Stackoverflow
Solution 15 - Javascriptsudharsan gandhiView Answer on Stackoverflow
Solution 16 - JavascriptAli80View Answer on Stackoverflow