I write a lot of Javascript and ran into a pretty awful bug today that took me 3 hours to figure out. In the hopes of this saving someone else an equal amount of time I am writing about how I fixed it here.
I am developing a chrome extension that makes the internet private again. No tracking, no bad actors, etc. I have written a few libraries to use for the project for simple things like auth with google and http requests.
I usually use things like axios but wanted to roll my own and interface with raw XML HTTPRequests. Last night I was running out the door but made a few code changes I didn't quite think through. Bad move.
I have 2 methods that ended up being the way to fix.
In my auth.js method I was passed an object from Google like so:
{ "email": "kameronkales", "id": 1298179834}
In my history.js I was creating what I thought was an object (but was really an array).
I created the array like so:
var i;
var example_list = []
for (i = 0; i < bad_list.length; i++) {
var clean = bad_list[i]
example_list.push(clean)
}
This was not doing what I thought.
When I console.logged the data from example_list I was getting:
{
0: "https://google.com",
1: "https://google.com",
2: "https://google.com
}
Which, now seems obviously wrong. But I didn't realize until looking at the data.
JSON.stringify doesn't know what to do with those int fields. So, it drops them.
When I would run
JSON.stringify(example_list)
I would be returned this:
[]
And it drove me insane! Because I knew the array had fields in it. But I wasn't paying enough attention (I know, I know. Won't do that again.)
I ended up being able to fix this by the following:
var urls = {} <= an actual object
.....HTTP requests to get the data I wanted
urls['data'] = data
This now returns a nice object that looks like the following:
{
'data': 'https://google.com',
'data': 'https://google.com',
'data' : 'https://google.com'
}
There are a ton of ways to clean this up and format better. But I spent way too long trying to figure out why this simple method didn't work the way I wanted it too.
Hopefully this saves you some time.
Top comments (3)
Hey there,
thanks for writing this.
I tried this and it works for me with node 11. Maybe I'm missing something?
The console output for your initial example list looks like an object judging by the curly braces.
This is what the node REPL does for me:
|> JSON.stringify({1:"abc"})
'{"1":"abc"}'
|> let x = []
undefined
|> x[1] = "abc"
'abc'
|> JSON.stringify(x)
'[null,"abc"]'
As you can see both numbers as property names and arrays with unset indexes work fine with JSON.stringify.
Numerical property names are in the specs. I think author's screenshot of first log { 0: ..., 1:... } is not correct.
Thanks for writing. It s really helpfull for me