JavaScript: parsing a string object using JSON.parse removes links

I am trying to deeply clone an object, say "a" with k = JSON.parse (JSON.stringify (a)). It is very important to use the stringify method, since I am trying to save an object to a file and then load it.

I came across a problem with references to a cloned object, which is illustrated below:

var obj={}; obj.importantProperty={s:2}; obj.c=obj.importantProperty; obj.d=obj.importantProperty; console.log( obj.c === obj.d ); // Returns true var cloned = JSON.parse(JSON.stringify(obj)); console.log( cloned.c === cloned.d ); // Returns false 
I need the links to be supported when using JSON.parse, in the above example it is not. In my project, the object is much more complex, but in the end it comes down to the above example.

Thanks in advance to everyone who helps me :)

+5
source share
2 answers

The proper way to do something like this should be to store the shared reference object separately and reference it using an identifier.

For example, you can hold importantProperty objects in an array and use the index as an identifier:

 var importantProperties = [ { s: 1 }, { s: 2 }, { s: 3 } ]; var obj = {}; obj.importantProperty = importantProperties[1]; obj.c = obj.importantProperty; obj.d = obj.importantProperty; 

Then, when you gate the object, you replace the reference object with its index:

 var stringified = JSON.stringify(obj, function(key, value) { if (key) { return importantProperties.indexOf(value); } return value; }); console.log(stringified); // prints {"importantProperty":1,"c":1,"d":1} 

And then when you analyze, you just change the process to animate the links:

 var parsed = JSON.parse(stringified, function(key, value) { if (key) { return importantProperties[value]; } return value; }); console.log(parsed.c === parsed.d && parsed.d === parsed.importantProperty); // prints true 

Now the example above works for your code example under the assumption that all properties in obj are objects from the importantProperties array. If this is not the case, and these are only certain properties that are importantProperties objects, you need to check this when replacing / restoring.
Assuming these objects are the properties "importantProperty", "c" and "d":
if (['importantProperty', 'c', 'd'].includes(key)) instead of if (key)

If this is not enough and you do not want the property name to have anything to do with whether this value is an importantProperties object, you need to specify this value along with the identifier. Here is an example of how this can be done:

 // Replacing JSON.stringify(obj, function(k, value) { if (importantProperties.includes(value)) { return 'ImportantProperty[' + importantProperties.indexOf(value) + ']'; } return value; }); // Reviving JSON.parse(stringified, function(k, value) { if (/^ImportantProperty\[\d+\]$/.test(value)) { var index = Number( value.match(/\d+/)[0] ); return importantProperties[index]; } return value; }); 
0
source

It is not possible to achieve the desired result using JSON, since the JSON format can contain only a limited number of data types ( http://json.org/ ) and when you pull the object to JSON, some information is lost.

There may be some other serialization method, but I would recommend that you look for a different approach for storing data.

0
source

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


All Articles