How To convert JSON data To Cyclic Object Value? - javascript

I am able to convert cyclic Object to JSON. Now, i want to convert JSON to cyclic Object
//Cyclic to JSON conversion which works fine
<script>
var seatObj;
seen = [];
var replacer = function(key, value) {
if (value != null && typeof value == "object") {
if (seen.indexOf(value) >= 0) {
return;
}
seen.push(value);
}
return value;
};
seatObj = JSON.stringify(obj.part.data, replacer);
</script>

If you want to restore your cyclic information, you need to retain it somehow. Traditionally you would generate or keep track of existing object ids to retain the information in your json output.

Related

How can I deserialize a nested React Element which is an elemen of a nested object inside an array?

Hey guys I have a tough one here
I need to store and retrieve an object with nested elements and a function which returns serialized in the clients localStorage. As for the storing and retrieving, it works. But I am having an issue with functions which have been stringyfied, but won't go back to be actual functions anymore.
Here is an example of an array element:
As far as I am aware, this is called serialized in the JSON-Jargon. And the goal would be to unserialize them again in order to make them function again. In order to be able to store functions in the JSON format, I had "replace and revive" the arrays which had to be stored.
let replacer = (key, value) => {
if (typeof value === "function") {
return value.toString();
}
return value;
I turn functions to string and return them to the JSON. I invoke this helper function like this:
localStorage.setItem(
"currentConfiguration",
JSON.stringify(
tableRef.current.dataManager.columns,
replacer,
2
)
Here is the code which is actually supposed to do: Undo what the replacer did and return actual functions instead of their strings.
let reviver = (key, value) => {
if (typeof value === "string" && value.indexOf("function ") === 0) {
let functionTemplate = `(${value})`;
return eval((functionTemplate));
}
return value;
};
Currently I am facing this screen whenever I try to render:
Would appriciate if anyone could lend a helping hand

How do I get JSON data from one HTML Apps Script file in another HTML file?

I have some data in a file called data.json.html in an Apps Script project that I would like to access from JavaScript. The file looks like this:
<script>
var data = {"book1":{"1":25, "2":17}, "book2":{"1":37, "2":4, "3":12}};
</script>
I have tried to access this data by the following means:
Attempt #1
<script type="text/javascript" src="data.json"></script>
<script>
var books = JSON.parse(data);
</script>
Attempt #2
<?!= include("data.json") ?>
<script>
var books = JSON.parse(data);
</script>
Neither one of these worked. Can anyone tell me the correct way of doing this?
Edit: Sorry I forgot to include information about what "it doesn't work" means. Basically, the data doesn't make it into the variable, it's supposed to go into, and there's no error telling me what happened in the execution transcript.
If anyone wants to look at the full script, it is embedded in the Google Doc here. Just go to Tools > Script editor... to find it.
This may not be optimum but it will work.
Depending whether the html file is on your domain (then just simply access it) otherwise retrieve the data by an HTTP request. Then use this to find the son location and its length:
var string = "responseString",
substring = "book1";
var jsonStr = str.substring(string.indexOf(substring), 100);
This can be used if you know for example the length is 100 from the matching book1. If you don't know the length use something like above ton find location of "};".
Then use jsonStr in the following to get the key values.
//return an array of objects according to key, value, or key and value matching
function getObjects(obj, key, val) {
var objects = [];
for (var i in obj) {
if (!obj.hasOwnProperty(i)) continue;
if (typeof obj[i] == 'object') {
objects = objects.concat(getObjects(obj[i], key, val));
} else
//if key matches and value matches or if key matches and value is not passed (eliminating the case where key matches but passed value does not)
if (i == key && obj[i] == val || i == key && val == '') { //
objects.push(obj);
} else if (obj[i] == val && key == ''){
//only add if the object is not already in the array
if (objects.lastIndexOf(obj) == -1){
objects.push(obj);
}
}
}
return objects;
}
//return an array of values that match on a certain key
function getValues(obj, key) {
var objects = [];
for (var i in obj) {
if (!obj.hasOwnProperty(i)) continue;
if (typeof obj[i] == 'object') {
objects = objects.concat(getValues(obj[i], key));
} else if (i == key) {
objects.push(obj[i]);
}
}
return objects;
}
//return an array of keys that match on a certain value
function getKeys(obj, val) {
var objects = [];
for (var i in obj) {
if (!obj.hasOwnProperty(i)) continue;
if (typeof obj[i] == 'object') {
objects = objects.concat(getKeys(obj[i], val));
} else if (obj[i] == val) {
objects.push(i);
}
}
return objects;
}
var json = '{"glossary":{"title":"example glossary","GlossDiv":{"title":"S","GlossList":{"GlossEntry":{"ID":"SGML","SortAs":"SGML","GlossTerm":"Standard Generalized Markup Language","Acronym":"SGML","Abbrev":"ISO 8879:1986","GlossDef":{"para":"A meta-markup language, used to create markup languages such as DocBook.","ID":"44","str":"SGML","GlossSeeAlso":["GML","XML"]},"GlossSee":"markup"}}}}}';
var js = JSON.parse(json);
//example of grabbing objects that match some key and value in JSON
console.log(getObjects(js,'ID','SGML'));
//returns 1 object where a key names ID has the value SGML
//example of grabbing objects that match some key in JSON
console.log(getObjects(js,'ID',''));
//returns 2 objects since keys with name ID are found in 2 objects
//example of grabbing obejcts that match some value in JSON
console.log(getObjects(js,'','SGML'));
//returns 2 object since 2 obects have keys with the value SGML
//example of grabbing objects that match some key in JSON
console.log(getObjects(js,'ID',''));
//returns 2 objects since keys with name ID are found in 2 objects
//example of grabbing values from any key passed in JSON
console.log(getValues(js,'ID'));
//returns array ["SGML", "44"]
//example of grabbing keys by searching via values in JSON
console.log(getKeys(js,'SGML'));
//returns array ["ID", "SortAs", "Acronym", "str"]
In that case you can use this to access a local file:
function readTextFile(file)
{
var rawFile = new XMLHttpRequest();
rawFile.open("GET", file, false);
rawFile.onreadystatechange = function ()
{
if(rawFile.readyState === 4)
{
if(rawFile.status === 200 || rawFile.status == 0)
{
var allText = rawFile.responseText;
alert(allText);
}
}
}
rawFile.send(null);
}
and file in the first line will be the path and file name.

Merging 2 arrays in local storage in javascript

I am trying to append an array of objects(new) to the local storage which already has some array of objects(previous) built in. Specifically, I want to merge these 2 arrays (previous and new) in the local storage.
Have tried the below code :
function appendToStorage(name, data)
{
var old = localStorage.getItem(name);
if(old === null)
old = "";
localStorage.setItem(name, old.concat(data));
}
appendToStorage('ObjAry', JSON.stringify(objectIdArray));
And this is the output that I am getting :
["IrGszUBa0F","l366vn6mPa","2qn7JUoRwg","s2fZa0mXnb","WIaXLwmXRa"]["ZKHtnHoHgH","rtbI1sDfPm","U1eVDi9bNM","tUGNCl6hNl","lkq6tswVsZ"]
All I want is that, the second array should append to the first array so the output becomes :
["IrGszUBa0F","l366vn6mPa","2qn7JUoRwg","s2fZa0mXnb","WIaXLwmXRa","ZKHtnHoHgH","rtbI1sDfPm","U1eVDi9bNM","tUGNCl6hNl","lkq6tswVsZ"]
Can anyone guide me on what I am doing wrong ?
You are pretty close, there are just three small mistakes:
You are stringifying the array before concatenating it (so you are attaching a string to an array).
The default value for old is a string, which should probably be an array?
In order to use the array from localstorage, you need to parse it again using JSON.parse.
The resulting code would then be:
function appendToStorage(name, data)
{
var old = localStorage.getItem(name);
if(old == null) {
old = [];
} else {
old = JSON.parse(old);
}
localStorage.setItem(name, JSON.stringify(old.concat(data)));
}
appendToStorage('ObjAry', objectIdArray);
If your local storage entry could contain other values as well, you could add a try ... catch block to your code to make sure that JSON.parse doesn't blow up if it fails to parse the value:
function appendToStorage(name, data)
{
var old = localStorage.getItem(name);
try {
old = JSON.parse(old);
} catch(e) {
old = [];
}
localStorage.setItem(name, JSON.stringify(old.concat(data)));
}
appendToStorage('ObjAry', objectIdArray);
You're concatenating the whole object returning from
JSON.stringify(objectIdArray)
Try
appendToStorage('ObjAry', objectIdArray);
LocalStorage stores a string values by a string key. To store arrays/objects as string we serialize them into JSON. So you need to parse JSON after getItem, merge parsed value with new portion of data, convert merged object to JSON and pass it to setItem.
function appendToStorage(name, data) {
var old = localStorage.getItem(name) || '[]';
var oldObject = JSON.parse(old) || [];
var merged = oldObject.concat(data);
localStorage.setItem(name, JSON.stringify(merged));
}
appendToStorage('ObjAry', objectIdArray);

Extracting data from JSON.stringify

The data I receive back from my JSON.stringify looks like this.
{"action":"deleted","data":{"latitude":9,"longititude":8,"_type":"locationcurrent","id":49,"user":"7"}}
But I can not seem to get the data inside of the objects. Mainly I want the value for action, "deleted", and the values for my data, like id:"49". But im having problems using this equation to try and get the data out.
function replacer(key, value) {
if (typeof value === "string") {
return value;
}
return undefined;
}
var jsonString = JSON.stringify(message, replacer);
console.log(jsonString);
All I get back from this is,
data:{}
Your problem is that the first value that is passed to the replacer is the object itself. You replace this object by undefined because it is not of the type string.
You need it change it that way:
function replacer(key, value) {
if ( key === '' || typeof value === "string") {
return value;
}
return undefined;
}
But as Phatjam98 said, it does not make much sense to filter out one value that way.

Checking for duplicate Javascript objects

TL;DR version: I want to avoid adding duplicate Javascript objects to an array of similar objects, some of which might be really big. What's the best approach?
I have an application where I'm loading large amounts of JSON data into a Javascript data structure. While it's a bit more complex than this, assume that I'm loading JSON into an array of Javascript objects from a server through a series of AJAX requests, something like:
var myObjects = [];
function processObject(o) {
myObjects.push(o);
}
for (var x=0; x<1000; x++) {
$.getJSON('/new_object.json', processObject);
}
To complicate matters, the JSON:
is in an unknown schema
is of arbitrary length (probably not enormous, but could be in the 100-200 kb range)
might contain duplicates across different requests
My initial thought is to have an additional object to store a hash of each object (via JSON.stringify?) and check against it on each load, like this:
var myHashMap = {};
function processObject(o) {
var hash = JSON.stringify(o);
// is it in the hashmap?
if (!(myHashMap[hash])) {
myObjects.push(o);
// set the hashmap key for future checks
myHashMap[hash] = true;
}
// else ignore this object
}
but I'm worried about having property names in myHashMap that might be 200 kb in length. So my questions are:
Is there a better approach for this problem than the hashmap idea?
If not, is there a better way to make a hash function for a JSON object of arbitrary length and schema than JSON.stringify?
What are the possible issues with super-long property names in an object?
I'd suggest you create an MD5 hash of the JSON.stringify(o) and store that in your hashmap with a reference to your stored object as the data for the hash. And to make sure that there are no object key order differences in the JSON.stringify(), you have to create a copy of the object that orders the keys.
Then, when each new object comes in, you check it against the hash map. If you find a match in the hash map, then you compare the incoming object with the actual object that you've stored to see if they are truly duplicates (since there can be MD5 hash collisions). That way, you have a manageable hash table (with only MD5 hashes in it).
Here's code to create a canonical string representation of an object (including nested objects or objects within arrays) that handles object keys that might be in a different order if you just called JSON.stringify().
// Code to do a canonical JSON.stringify() that puts object properties
// in a consistent order
// Does not allow circular references (child containing reference to parent)
JSON.stringifyCanonical = function(obj) {
// compatible with either browser or node.js
var Set = typeof window === "object" ? window.Set : global.Set;
// poor man's Set polyfill
if (typeof Set !== "function") {
Set = function(s) {
if (s) {
this.data = s.data.slice();
} else {
this.data = [];
}
};
Set.prototype = {
add: function(item) {
this.data.push(item);
},
has: function(item) {
return this.data.indexOf(item) !== -1;
}
};
}
function orderKeys(obj, parents) {
if (typeof obj !== "object") {
throw new Error("orderKeys() expects object type");
}
var set = new Set(parents);
if (set.has(obj)) {
throw new Error("circular object in stringifyCanonical()");
}
set.add(obj);
var tempObj, item, i;
if (Array.isArray(obj)) {
// no need to re-order an array
// but need to check it for embedded objects that need to be ordered
tempObj = [];
for (i = 0; i < obj.length; i++) {
item = obj[i];
if (typeof item === "object") {
tempObj[i] = orderKeys(item, set);
} else {
tempObj[i] = item;
}
}
} else {
tempObj = {};
// get keys, sort them and build new object
Object.keys(obj).sort().forEach(function(item) {
if (typeof obj[item] === "object") {
tempObj[item] = orderKeys(obj[item], set);
} else {
tempObj[item] = obj[item];
}
});
}
return tempObj;
}
return JSON.stringify(orderKeys(obj));
}
And, the algorithm
var myHashMap = {};
function processObject(o) {
var stringifiedCandidate = JSON.stringifyCanonical(o);
var hash = CreateMD5(stringifiedCandidate);
var list = [], found = false;
// is it in the hashmap?
if (!myHashMap[hash] {
// not in the hash table, so it's a unique object
myObjects.push(o);
list.push(myObjects.length - 1); // put a reference to the object with this hash value in the list
myHashMap[hash] = list; // store the list in the hash table for future comparisons
} else {
// the hash does exist in the hash table, check for an exact object match to see if it's really a duplicate
list = myHashMap[hash]; // get the list of other object indexes with this hash value
// loop through the list
for (var i = 0; i < list.length; i++) {
if (stringifiedCandidate === JSON.stringifyCanonical(myObjects[list[i]])) {
found = true; // found an exact object match
break;
}
}
// if not found, it's not an exact duplicate, even though there was a hash match
if (!found) {
myObjects.push(o);
myHashMap[hash].push(myObjects.length - 1);
}
}
}
Test case for jsonStringifyCanonical() is here: https://jsfiddle.net/jfriend00/zfrtpqcL/
Maybe. For example if You know what kind object goes by You could write better indexing and searching system than JS objects' keys. But You could only do that with JavaScript and object keys are written in C...
Must Your hashing be lossless or not? If can than try to lose compression (MD5). I guessing You will lose some speed and gain some memory. By the way, do JSON.stringify(o) guarantees same key ordering. Because {foo: 1, bar: 2} and {bar: 2, foo: 1} is equal as objects, but not as strings.
Cost memory
One possible optimization:
Instead of using getJSON use $.get and pass "text" as dataType param. Than You can use result as Your hash and convert to object afterwards.
Actually by writing last sentence I though about another solution:
Collect all results with $.get into array
Sort it with buildin (c speed) Array.sort
Now You can easily spot and remove duplicates with one for
Again different JSON strings can make same JavaScript object.

Categories

Resources