Skip to content

Instantly share code, notes, and snippets.

@kylebakerio
Last active August 29, 2015 14:25
Show Gist options
  • Save kylebakerio/9e466eec0efdd0994b92 to your computer and use it in GitHub Desktop.
Save kylebakerio/9e466eec0efdd0994b92 to your computer and use it in GitHub Desktop.
function stringifyJSON(subject) {
var output = '';
var type = typeof subject;
if (type === 'number') {
return subject.toString();
} else if (subject === null) {
return 'null';
} else if (type === "boolean") {
return subject.toString();
} else if (type === "string") {
return ('"' + (subject) + '"')
} else if (Object.prototype.toString.call(subject) === '[object Array]') {
var index = subject.length;
output += '[';
subject.forEach(function(val){
if (typeof val === "number") {
// because for some reason we stringify numbers outside of the arrays,
// but not inside the arrays... ok... talk about a 'gotcha'. O_o;
output += val;
} else {
// let all other values in the array be stringified according to the rules above.
output += stringifyJSON(val);
}
index--;
if (index > 0) {output = output.concat(",")}
});
output += ']';
return output;
} else if (Object.prototype.toString.call(subject) === '[object Object]') {
var index = Object.keys(subject).length;
output += '{';
for (var key in subject) {
if ( !((key === 'functions') || (key === "undefined")) ) {
output += (stringifyJSON(key) + ":" + stringifyJSON(subject[key]))
index--;
if (index > 0) { output += "," }
}
}
output += '}';
}
return output;
}
///test values
var stringifiableObjects = [
9,
null,
true,
false,
"Hello world",
[],
[8],
["hi"],
[8, "hi"],
[1, 0, -1, -0.3, 0.3, 1343.32, 3345, 0.00011999999999999999],
[8, [[],3,4]],
[[[["foo"]]]],
{},
{"a": "apple"},
{"foo": true, "bar": false, "baz": null},
{"boolean, true": true, "boolean, false": false, "null": null },
// basic nesting
{"a":{"b":"c"}},
{"a":["b", "c"]},
[{"a":"b"}, {"c":"d"}],
{"a":[],"c": {}, "b": true}
];
var unstringifiableValues = [
{
'functions': function(){},
'undefined': undefined
}
];
//
// start tests
//
var passed = 0, failed = 0;
unstringifiableValues.concat(stringifiableObjects).reverse().forEach(function(val){
JSON.stringify(val) === stringifyJSON(val) ?
passed++ : (failed++,
console.log("what type is it? " + typeof val),
console.log(Object.prototype.toString.call(val)),
// console.log("which statement did it hit? " + hit);
console.log("original input to be stringified:"),
console.dir(val),
console.log("which should be turned into:"),
console.dir(JSON.stringify(val)),
console.log("this is what my script currently turns it into:"),
console.dir(stringifyJSON(val)),
console.log("---- \n")
)
})
console.log("Passed " + passed + " out of " + (passed + failed) + "; failed " + failed)
@kylebakerio
Copy link
Author

has a nice built in self tester now.

@kylebakerio
Copy link
Author

working on it test by test

@kylebakerio
Copy link
Author

much prettier test results.

@kylebakerio
Copy link
Author

last shows up first, now.

also has test counter.

@kylebakerio
Copy link
Author

supper baffled at {} right now... for some reason, even though Object.prototype.toString.call({}) === '[object Array]' is false (it returns [object Object]...), it somehow passes that conditional statement and runs the array block...

Like, wtf? I don't feel tired enough to assume I'm screwing up some basic logic, but I can't imagine how else I could be getting this wrong...

edit: saved it as a variable right there and outputted it... somehow { } is getting turned in to [ ]. Well that's just all kinds of fun!

...WTF.

O_o

@kylebakerio
Copy link
Author

Ok, so, I think I am actually hitting a bug, because now after some slight changes that should have zero relevance to this (declaring some troubleshooting variables, removing "reverse()" from the execution context...), it is now hitting the 'string' section, not the 'array' section. so, something about the prior forEach loops being run must affect the context?

Sure enough, when I make it run the forEach loop in reverse() again, it now hits the array block...

edit... the plot gets thicker... I was thinking something was modified somehow in my environment by running everything through a loop, but... when I run console.dir(stringifyJ(stringifiableObjects[12])) directly, and set the stringifyJ function to console.log(hit), it still shows it as hitting the array block... so, that must mean that something in stringifyJ itself mutates it into array brackets... right?

....right?

except... sticking console.log(subject) right after the block show it as being {}...

SOLUTION:

it was never setting the 'hit' variable when the {} value was going through the function... but just returning the hit value from the previous time. the section of the function that was supposed to set hit as bottom was broken.

Should have thought to check that. one more little piece of experience gained. figured it out by trying to run console.log statements, while not doing a for loop (because that would have the prior object logging in there, since they were correctly going through the array loop), and noticing they weren't running, leading me to wonder if there were somehow a possibility that it wasn't running at all.

The reason it showed hit as being array even when I called it alone, is because technically I was calling it after I had just called it on every other stringifiable object, and so it was leftover from the prior forEach loop. I didn't have a clean testing environment, in other words; I was being lazy and using the same environment without commenting out my old code.

So, the hazards of 'global variables'. Old news, I guess. experience gained.

Troubleshooting step I missed: when I saw that it was impossible for it to be entering that block, because I knew the statement would be false, I should have doubted the system that told me it was entering the block (which is code I wrote).

@kylebakerio
Copy link
Author

Now passing 17/20

@kylebakerio
Copy link
Author

passed 20. recursion is a beautiful thing.

@kylebakerio
Copy link
Author

there are more tests... needs to do things with undefined and functions... adding those tests...

@kylebakerio
Copy link
Author

now it passes 21 out of 21. and that actually now passes the mocha test suite. that took longer than it should have, but great learning experience.

@kylebakerio
Copy link
Author

Went back and polished both the code and the text, after lessons learned from making a ternary version.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment