Reliable way to test serialization of objects in JavaScript

Is there a known method or library that already has a helper for evaluating whether an object is serializable in JavaScript?

I tried the following, but it does not cover the prototype properties, so it provides false positives:

_.isEqual(obj, JSON.parse(JSON.stringify(obj)) 

There is another lodash function that can bring me closer to the truth, _.isPlainObject . However, while _.isPlainObject(new MyClass()) returns false , _.isPlainObject({x: new MyClass()}) returns true , so it must be applied recursively.

Before I decide on this, does anyone already know a reliable way to check if JSON.parse(JSON.stringify(obj)) will really have the same object as obj ?

+6
source share
4 answers

In the end, I created my own method that uses Underscore / Lodash _.isPlainObject . My function turned out to be similar to what @bardzusny suggested, but I also post mine, as I prefer simplicity / clarity. Feel free to outline the pros and cons.

 var _ = require('lodash'); exports.isSerializable = function(obj) { if (_.isUndefined(obj) || _.isNull(obj) || _.isBoolean(obj) || _.isNumber(obj) || _.isString(obj)) { return true; } if (!_.isPlainObject(obj) && !_.isArray(obj)) { return false; } for (var key in obj) { if (!exports.isSerializable(obj[key])) { return false; } } return true; }; 
+2
source
 function isSerializable(obj) { var isNestedSerializable; function isPlain(val) { return (typeof val === 'undefined' || typeof val === 'string' || typeof val === 'boolean' || typeof val === 'number' || Array.isArray(val) || _.isPlainObject(val)); } if (!isPlain(obj)) { return false; } for (var property in obj) { if (obj.hasOwnProperty(property)) { if (!isPlain(obj[property])) { return false; } if (typeof obj[property] == "object") { isNestedSerializable = isSerializable(obj[property]); if (!isNestedSerializable) { return false; } } } } return true; } 

Recursively iterate over all the given properties of the object. They may be:

  • simple objects ("an object created by the Object constructor or one with [[Prototype]] null." - from the lodash documentation)
  • arrays
  • strings , numbers , booleans
  • undefined

Any other value anywhere in the passed obj will lead to its understanding as "un-serializable".

(Honestly, I'm not quite sure that I have not missed checking for some serializable / non-serializable data types, which, in my opinion, depend on the definition of "serializable" - any comments and suggestions would be welcome.)

+3
source

Maybe I'm late ... but I came up with something much cleaner.

 const checkIfSerializable = (jsonObject) => { const cleanedJson = JSON.parse(JSON.stringify(jsonObject)); return _.isEqual(cleanedJson, jsonObject); }; const a = {test:123, abc: 345} checkIfSerializable(a) //true const b = {tt: ()=>{}, abc: 232}; checkIfSerializable(b) //false const c = {test:123,def:{test: 111}, abc: 345} checkIfSerializable(c) //true const d = {test:123,def:{test: 111, mm:()=>{}}, abc: 345} checkIfSerializable(d) //false 
0
source

Here are some versions of @treznik's solution from Lodashy ES6

  export function isSerialisable(obj) { const nestedSerialisable = ob => (_.isPlainObject(ob) || _.isArray(ob)) && _.every(ob, isSerialisable); return _.overSome([ _.isUndefined, _.isNull, _.isBoolean, _.isNumber, _.isString, nestedSerialisable ])(obj) } 

Test

  describe.only('isSerialisable', () => { it('string', () => { chk(isSerialisable('HI')); }); it('number', () => { chk(isSerialisable(23454)) }); it('null', () => { chk(isSerialisable(null)) }); it('undefined', () => { chk(isSerialisable(undefined)) }); it('plain obj', () => { chk(isSerialisable({p: 1, p2: 'hi'})) }); it('plain obj with func', () => { chkFalse(isSerialisable({p: 1, p2: () => {}})) }); it('nested obj with func', () => { chkFalse(isSerialisable({p: 1, p2: 'hi', n: { nn: { nnn: 1, nnm: () => {}}}})) }); it('array', () => { chk(isSerialisable([1, 2, 3, 5])) }); it('array with func', () => { chkFalse(isSerialisable([1, 2, 3, () => false])) }); it('array with nested obj', () => { chk(isSerialisable([1, 2, 3, { nn: { nnn: 1, nnm: 'Hi'}}])) }); it('array with newsted obj with func', () => { chkFalse(isSerialisable([1, 2, 3, { nn: { nnn: 1, nnm: () => {}}}])) }); }); _.isBoolean, _.isNumber, _.isString, nestedSerialisable ])(obj) } 
0
source

Source: https://habr.com/ru/post/988334/


All Articles