skip to Main Content

I’m trying to serialize a javascript object with about a hundred properties. 3 of those are implemented to log a warning when they are accessed (likely using a property getter implementation).

I wish to serialize the object except those 3 properties, and furthermore I don’t even want those 3 properties to be accessed.

I tried the following (using a replacer function):

const excludeProperties = ['badProp1', 'badProp2', 'badProp3']
JSON.stringify(theObject, (key, value) => excludeProperties.includes(key) ? undefined : value);

While the end result indeed excludes the properties from the JSON, it unfortunately doesn’t prevent those properties from being accessed behind-the-scenes, so the warnings still get thrown.

Can anyone think of a fairly simple (less-code) solution to ensure these keys are never accessed?


Steps to reproduce:

const obj = {
  goodProperty: "Serialize Me",
  get badProperty() {
    console.log("Warning: Accessed deprecated property")
    return "deprecated";
  }
};

console.log(JSON.stringify(obj));
// Output:
// Warning: Accessed deprecated property
// {"goodProperty":"Serialize Me","badProperty":"deprecated"} 

const excludeProperties = ["badProperty"];
console.log(JSON.stringify(obj, (key, value) => excludeProperties.includes(key) ? undefined : value));
// Output:
// Warning: Accessed deprecated property
// {"goodProperty":"Serialize Me"}

3

Answers


  1. You could use reduce() on Object.keys(obj) to create a new object with only the properties you’d like. This way it won’t trigger the getter.

    Using spread syntax will trigger it, so that’t not an option.

    const obj = {
      goodProperty: "Serialize Me",
      get badProperty() {
        console.log("Warning: Accessed deprecated property")
        return "deprecated";
      }
    };
    
    const excludeProperties = ["badProperty"];
    
    const objWithoutBadProperties = Object.keys(obj).reduce((p, c) => {
        if (!excludeProperties.includes(c)) {
            p[c] = obj[c];
        }
        return p;
    }, {});
    console.log(JSON.stringify(objWithoutBadProperties));
    Login or Signup to reply.
  2. You can add a toJSON() function to your object to get fine-grained control of your serialization:

    const obj = {
      goodProperty: "Serialize Me",
      get badProperty() {
        console.log("Warning: Accessed deprecated property")
        return "deprecated";
      },
    };
    
    obj.toJSON = function() {
        const exclude = [ "badProperty" ];
        const sanitizedObject = {};
        for (let prop in this) {
          if (!exclude.includes(prop)) sanitizedObject[prop] = this[prop];
        }
        return sanitizedObject;
    
        // Or, you can just return:
        // return { goodProperty: this.goodProperty };
    };
    
    console.log(JSON.stringify(obj));

    The benefit of this approach is that you can now be certain that the bad properties will never be accessed when serializing the object, no matter when or where stringify() is called.

    Login or Signup to reply.
  3. FP style

    const obj = {
      goodProperty: "Serialize Me",
      get badProperty() {
        console.log("Warning: Accessed deprecated property")
        return "deprecated";
      },
      toJSON() {
        return Object.keys(this)
          .filter(k => !['badProperty'].includes(k))
          .reduce((acc, cur) => {
            acc[cur] = this[cur];
            return acc
          }, {})
      }
    };
    
    console.log(JSON.stringify(obj))
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search