Two BSON types, namely BSON_TYPE_CODE and BSON_TYPE_CODEWSCOPE, fail to transition through their JSON representation.
In case of BSON_TYPE_CODE, its binary data will be different from the source document. That's especially weird because the JSON representation is restored with no difference.
In case of BSON_TYPE_CODEWSCOPE, both the binary data and the JSON representation will be different from the source document when scope is an empty document (note the additional space between the scope brackets). When scope is not empty, the binary data will differ.
Example:
#include <stdio.h> #include <bson.h> void test(const bson_t *src) { char *json = bson_as_json(src, 0); // src -> json bson_t *dst = bson_new_from_json(json, -1, 0); // json -> dst char *json_ = bson_as_json(dst, 0); // dst -> json_ BSON_ASSERT(json && dst && json_); // No errors printf("Testing %s\n", json); printf("... and %s\n", json_); printf("* as JSON - %s\n", strcmp(json, json_) ? "failed!!!" : "OK"); // Compare as JSON printf("* as binary - %s\n", !bson_equal(src, dst) ? "failed!!!" : "OK"); // Compare as binary printf("\n"); bson_destroy(dst); bson_free(json); bson_free(json_); } int main() { bson_t *b1 = bson_new(); bson_t *b2 = bson_new(); bson_t *b3 = bson_new(); bson_t *b4 = bson_new(); bson_t *scope = bson_new(); // All types roundtrip alright, for example: BSON_APPEND_BINARY(b1, "a", 0x80, "abc", 3); BSON_APPEND_MINKEY(b1, "b"); BSON_APPEND_REGEX(b1, "c", "abc", "def"); test(b1); // Except for these guys: BSON_APPEND_CODE(b2, "a", "abc"); test(b2); BSON_APPEND_CODE_WITH_SCOPE(b3, "a", "abc", scope); test(b3); BSON_APPEND_BOOL(scope, "bool", 1); // Non-empty scope now BSON_APPEND_CODE_WITH_SCOPE(b4, "a", "abc", scope); test(b4); bson_destroy(b1); bson_destroy(b2); bson_destroy(b3); bson_destroy(b4); bson_destroy(scope); return 0; }
Output:
Testing { "a" : { "$binary" : "YWJj", "$type" : "80" }, "b" : { "$minKey" : 1 }, "c" : { "$regex" : "abc", "$options" : "def" } } ... and { "a" : { "$binary" : "YWJj", "$type" : "80" }, "b" : { "$minKey" : 1 }, "c" : { "$regex" : "abc", "$options" : "def" } } * as JSON - OK * as binary - OK Testing { "a" : { "$code" : "abc" } } ... and { "a" : { "$code" : "abc" } } * as JSON - OK * as binary - failed!!! Testing { "a" : { "$code" : "abc", "$scope" : { } } } ... and { "a" : { "$code" : "abc", "$scope" : { } } } * as JSON - failed!!! * as binary - failed!!! Testing { "a" : { "$code" : "abc", "$scope" : { "bool" : true } } } ... and { "a" : { "$code" : "abc", "$scope" : { "bool" : true } } } * as JSON - OK * as binary - failed!!!