I'm trying to emulate the JSON.stringify function by doing a bit of "reverse engineering" by seeing the result of serializing an object or array to json. Next I put a jsfiddle of the emulation of a proper method.
"use strict"
const obj = {
"hello": "object",
"im_an_array": ["pos 0", "pos 1"],
22.4: [1, "Hola", null, undefined, false, 0],
"object": {
description: "im an object"
},
"date": new Date(),
"function": function(arg = "") {
alert("Hello "+arg+"!");
}
}
const arr = ["Hello", "array", 2, 2.1245, ["0", 1], null, new Date(), [false, [undefined, true, {param1: true, empty_obj: {}}, {empty_arr: []}, ""]]];
/****************** START OF FUNCION *************************/
JSON.cerealize = function(obj = {}) {
if (typeof obj !== "object") {
throw new TypeError("The parameter passed is not an object");
}
let str2 = "";
let openTag = "{";
let closeTag = "}";
let obj_type = "object";
let str3 = ""; //For setting keys and ':' for only when the value is not a function.
//KNOW IF IT IS AN ARRAY OR OBJECT FOR OPEN AND END TAGS
if (Array.isArray(obj)) { //If the passed object is an array, susbstitute the open and close tags and set the cached obj_type as array instead of object.
openTag = "[";
closeTag = "]";
obj_type = "array";
}
str2 += openTag;
//If object is a Function do nothing
for (const k in obj) {
//Cache the obj
const _obj = obj[k];
//Print the key of the object if it is not an array
str3 = "";
if (obj_type !== "array") {
typeof k === "string" ? str3 += ("\"" + k + "\"") : str3 += k;
str3 += ":";
}
if (typeof _obj !== "function") {
str2 += str3;
if (typeof _obj === "object") {
if (_obj === null) {
str2 += null;
} else if (_obj instanceof Date) {
str2 += "\"" + _obj.toJSON() + "\"";
} else {
str2 += JSON.cerealize(_obj);
}
}
else if(typeof _obj === "string") {
str2 += "\"" + _obj + "\"";
}
else if(typeof _obj === "undefined") {
str2 += null;
}
else {
str2 += _obj;
}
str2 += ",";
}
}
str2 += closeTag;
return str2.replace(/,(]|})/, "$1");
}
/**************************** END OF FUNCTION *************************/
window.onload = function() {
console.time('json_stringify_obj');
JSON.stringify(obj);
console.timeEnd('json_stringify_obj');
const p_obj = document.querySelector("#info_obj");
p_obj.textContent = JSON.cerealize(obj);
const p_arr = document.querySelector("#info_arr");
p_arr.textContent = JSON.cerealize(arr);
}
console.time('json_stringify_arr');
JSON.stringify(arr);
console.timeEnd('json_stringify_arr');
console.time('serial_obj');
JSON.cerealize(obj);
console.timeEnd('serial_obj');
console.time('serial_arr');
JSON.cerealize(arr);
console.timeEnd('serial_arr');
font-family: Lucida Console, Monospace, Arial, Sans-Serif;
<h2>
Recursion practice | Serializing objects
</h2>
<h3>serializing an object</h3>
<p id="info_obj">
<!-- obj info -->
</p>
<hr />
<h3>
<h3>Serializing an array</h3>
<p id="info_arr">
<!-- Array info -->
</p>
I have noticed that while in my case it appears undefined, in the original method doing JSON.stringify, the value is serialized as null.
Why? If undefined is a definable value why can't it be serialized as such? Couldn't you save an object entirely with inner methods? Since I have seen that JSON.stringify does not serialize the methods.
The short answer is: Because that's how JSON is defined .
The question that follows is why do you serialize Date as a string? (or how do I know if the serialized came from a Date or from a string that contained that value as a date).
The long answer is: to fix it you have to program or use a more complete library .
There are many. JSON4all https://www.npmjs.com/package/json4all does fine for undefined , Date , Regexp etc.
in your function
Where do you put
since str2 is a string it is equivalent to put
str2+="null"
you could put therefore I recommend you to try with:str2+="undefined"
There is another thing to be careful about, if what you are serializing is a string that contains quotes you are not "escaping" them correctly. Yes
is going to return you
["hola", "chau"]
and it is not what you want, you would want:["hola\", \"chau"]