I was recently trying to load the bson
(binary JSON) module in node.js
. The API docs were unclear, so I thought inspecting the objects would help me. The results of the inspection were baffling.
Finally I found out it was because I was using %j
which "lies" -- it doesn't print all of an object's dictionary keys! (I am using Python terminology for "attributes" as things referenced with a dot, and "dictionary keys" for things referenced with brackets, because I don't know the proper names for these things in JS.)
Here is an example:
var bson = require("bson");
console.log("bson as %%j: %j", bson);
console.log("bson as console.log: ", bson);
And here's the output:
bson as %j: {"BSONPure":{},"BSONNative":{}}
bson as console.log: { BSONPure:
{ Code: [Function: Code],
Symbol: [Function: Symbol],
BSON:
{ [Function: BSON]
BSON_INT32_MAX: 2147483647,
BSON_INT32_MIN: -2147483648,
BSON_INT64_MAX: 9223372036854776000,
BSON_INT64_MIN: -9223372036854776000,
...
I thought since x.key
is the same as x["key"]
, that this means attributes and dictionary keys are "the same thing" in JS. I found after experimenting that BSON.BSONPure
is {}
, however BSON.BSONPure.BSON
and BSON.BSONPure["BSON"]
are a function
object!
This leads me to believe that whatever "%j"
does, must somehow be excluding some keys. How does it decide which keys to exclude? Why would it even do that? JS is a really confusing language sometimes!
Related Github ticket: https://github.com/mongodb/js-bson/issues/97
Down in the node.js
source, the %j
placeholder results in a call to JSON.stringify()
on the passed argument.
The thing is, in passing your bson
variable, you are not passing an valid JSON
object. You are passing a node.js module which among other things has exported functions.
So, what happens when JSON.stringify()
hits a function?
If undefined, a function, or a symbol is encountered during conversion it is either omitted (when it is found in an object) or censored to null (when it is found in an array). (MDN)
So the behaviour you are seeing is completely expected, you are trying to log something as JSON
that is not valid JSON
.
> JSON.stringify({name: "Bob"})
> "{"name":"Bob"}"
> JSON.stringify({func: function(){}})
> "{}"