Skip to content

Commit

Permalink
fix(ejson): enable serialization of legacy ObjectID
Browse files Browse the repository at this point in the history
* don't require mongodb on browser tests

(part of the fix to #303)

* Revert "don't require mongodb on browser tests"

This reverts commit 3dc2cc1.

* EJSON serializing of ObjectID (capital D)

* Added newline at end of file
  • Loading branch information
justingrant authored and mbroadst committed Feb 14, 2019
1 parent ab790c9 commit ba98ccb
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 5 deletions.
7 changes: 6 additions & 1 deletion lib/extended_json.js
Expand Up @@ -268,8 +268,13 @@ function serializeValue(value, options) {
function serializeDocument(doc, options) {
if (doc == null || typeof doc !== 'object') throw new Error('not an object instance');

// the "document" is a BSON type
// the "document" is really just a BSON type
if (doc._bsontype) {
if (doc._bsontype === 'ObjectID') {
// Deprecated ObjectID class with capital "D" is still used (e.g. by 'mongodb' package). It has
// no "toExtendedJSON" method, so convert to new ObjectId (lowercase "d") class before serializing
doc = ObjectId.createFromHexString(doc.toString());
}
if (typeof doc.toExtendedJSON === 'function') {
// TODO: the two cases below mutate the original document! Bad. I don't know
// enough about these two BSON types to know how to safely clone these objects, but
Expand Down
53 changes: 49 additions & 4 deletions test/node/extended_json_tests.js
Expand Up @@ -16,10 +16,26 @@ const Long = BSON.Long;
const MaxKey = BSON.MaxKey;
const MinKey = BSON.MinKey;
const ObjectID = BSON.ObjectID;
const ObjectId = BSON.ObjectId;
const BSONRegExp = BSON.BSONRegExp;
const BSONSymbol = BSON.BSONSymbol;
const Timestamp = BSON.Timestamp;

// test the old ObjectID class because MongoDB drivers still return it
// fall back to BSON's ObjectId in browser tests
function getOldObjectID() {
try {
// do a dynamic resolve to avoid exception when running browser tests
const file = require.resolve('mongodb');
return require(file).ObjectID;
}
catch (e) {
return ObjectId; // if mongo is unavailable, e.g. browsers, just re-use BSON's
}
}

const OldObjectID = getOldObjectID();

describe('Extended JSON', function() {
let doc = {};

Expand All @@ -41,7 +57,9 @@ describe('Extended JSON', function() {
long: Long.fromNumber(200),
maxKey: new MaxKey(),
minKey: new MinKey(),
objectId: ObjectID.createFromHexString('111111111111111111111111'),
objectId: ObjectId.createFromHexString('111111111111111111111111'),
objectID: ObjectID.createFromHexString('111111111111111111111111'),
oldObjectID: OldObjectID.createFromHexString('111111111111111111111111'),
regexp: new BSONRegExp('hello world', 'i'),
symbol: new BSONSymbol('symbol'),
timestamp: Timestamp.fromNumber(1000),
Expand All @@ -55,7 +73,7 @@ describe('Extended JSON', function() {
it('should correctly extend an existing mongodb module', function() {
// Serialize the document
var json =
'{"_id":{"$numberInt":"100"},"gh":{"$numberInt":"1"},"binary":{"$binary":{"base64":"AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+Pw==","subType":"00"}},"date":{"$date":{"$numberLong":"1488372056737"}},"code":{"$code":"function() {}","$scope":{"a":{"$numberInt":"1"}}},"dbRef":{"$ref":"tests","$id":{"$numberInt":"1"},"$db":"test"},"decimal":{"$numberDecimal":"100"},"double":{"$numberDouble":"10.1"},"int32":{"$numberInt":"10"},"long":{"$numberLong":"200"},"maxKey":{"$maxKey":1},"minKey":{"$minKey":1},"objectId":{"$oid":"111111111111111111111111"},"regexp":{"$regularExpression":{"pattern":"hello world","options":"i"}},"symbol":{"$symbol":"symbol"},"timestamp":{"$timestamp":{"t":0,"i":1000}},"int32Number":{"$numberInt":"300"},"doubleNumber":{"$numberDouble":"200.2"},"longNumberIntFit":{"$numberLong":"7036874417766400"},"doubleNumberIntFit":{"$numberLong":"19007199250000000"}}';
'{"_id":{"$numberInt":"100"},"gh":{"$numberInt":"1"},"binary":{"$binary":{"base64":"AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+Pw==","subType":"00"}},"date":{"$date":{"$numberLong":"1488372056737"}},"code":{"$code":"function() {}","$scope":{"a":{"$numberInt":"1"}}},"dbRef":{"$ref":"tests","$id":{"$numberInt":"1"},"$db":"test"},"decimal":{"$numberDecimal":"100"},"double":{"$numberDouble":"10.1"},"int32":{"$numberInt":"10"},"long":{"$numberLong":"200"},"maxKey":{"$maxKey":1},"minKey":{"$minKey":1},"objectId":{"$oid":"111111111111111111111111"},"objectID":{"$oid":"111111111111111111111111"},"oldObjectID":{"$oid":"111111111111111111111111"},"regexp":{"$regularExpression":{"pattern":"hello world","options":"i"}},"symbol":{"$symbol":"symbol"},"timestamp":{"$timestamp":{"t":0,"i":1000}},"int32Number":{"$numberInt":"300"},"doubleNumber":{"$numberDouble":"200.2"},"longNumberIntFit":{"$numberLong":"7036874417766400"},"doubleNumberIntFit":{"$numberLong":"19007199250000000"}}';

assert.equal(json, EJSON.stringify(doc, null, 0, { relaxed: false }));
});
Expand Down Expand Up @@ -98,17 +116,36 @@ describe('Extended JSON', function() {
});

it('should correctly serialize bson types when they are values', function() {
var serialized = EJSON.stringify(new ObjectID('591801a468f9e7024b6235ea'), { relaxed: false });
var serialized = EJSON.stringify(new ObjectId('591801a468f9e7024b6235ea'), { relaxed: false });
expect(serialized).to.equal('{"$oid":"591801a468f9e7024b6235ea"}');
serialized = EJSON.stringify(new ObjectID('591801a468f9e7024b6235ea'), { relaxed: false });
expect(serialized).to.equal('{"$oid":"591801a468f9e7024b6235ea"}');
serialized = EJSON.stringify(new OldObjectID('591801a468f9e7024b6235ea'), { relaxed: false });
expect(serialized).to.equal('{"$oid":"591801a468f9e7024b6235ea"}');

serialized = EJSON.stringify(new Int32(42), { relaxed: false });
expect(serialized).to.equal('{"$numberInt":"42"}');
serialized = EJSON.stringify(
{
_id: { $nin: [new ObjectId('591801a468f9e7024b6235ea')] }
},
{ relaxed: false }
);
expect(serialized).to.equal('{"_id":{"$nin":[{"$oid":"591801a468f9e7024b6235ea"}]}}');
serialized = EJSON.stringify(
{
_id: { $nin: [new ObjectID('591801a468f9e7024b6235ea')] }
},
{ relaxed: false }
);
expect(serialized).to.equal('{"_id":{"$nin":[{"$oid":"591801a468f9e7024b6235ea"}]}}');
serialized = EJSON.stringify(
{
_id: { $nin: [new OldObjectID('591801a468f9e7024b6235ea')] }
},
{ relaxed: false }
);
expect(serialized).to.equal('{"_id":{"$nin":[{"$oid":"591801a468f9e7024b6235ea"}]}}');

serialized = EJSON.stringify(new Binary(new Uint8Array([1, 2, 3, 4, 5])), { relaxed: false });
expect(serialized).to.equal('{"$binary":{"base64":"AQIDBAU=","subType":"00"}}');
Expand All @@ -122,7 +159,7 @@ describe('Extended JSON', function() {
var parsed = EJSON.parse(input);

expect(parsed).to.deep.equal({
result: [{ _id: new ObjectID('591801a468f9e7024b623939'), emptyField: null }]
result: [{ _id: new ObjectId('591801a468f9e7024b623939'), emptyField: null }]
});
});

Expand Down Expand Up @@ -170,7 +207,9 @@ describe('Extended JSON', function() {
long: new Long(234),
maxKey: new MaxKey(),
minKey: new MinKey(),
objectId: ObjectId.createFromHexString('111111111111111111111111'),
objectID: ObjectID.createFromHexString('111111111111111111111111'),
oldObjectID: OldObjectID.createFromHexString('111111111111111111111111'),
bsonRegExp: new BSONRegExp('hello world', 'i'),
symbol: new BSONSymbol('symbol'),
timestamp: new Timestamp()
Expand All @@ -187,7 +226,9 @@ describe('Extended JSON', function() {
long: { $numberLong: '234' },
maxKey: { $maxKey: 1 },
minKey: { $minKey: 1 },
objectId: { $oid: '111111111111111111111111' },
objectID: { $oid: '111111111111111111111111' },
oldObjectID: { $oid: '111111111111111111111111' },
bsonRegExp: { $regularExpression: { pattern: 'hello world', options: 'i' } },
symbol: { $symbol: 'symbol' },
timestamp: { $timestamp: { t: 0, i: 0 } }
Expand All @@ -205,7 +246,9 @@ describe('Extended JSON', function() {
long: { $numberLong: '234' },
maxKey: { $maxKey: 1 },
minKey: { $minKey: 1 },
objectId: { $oid: '111111111111111111111111' },
objectID: { $oid: '111111111111111111111111' },
oldObjectID: { $oid: '111111111111111111111111' },
bsonRegExp: { $regularExpression: { pattern: 'hello world', options: 'i' } },
symbol: { $symbol: 'symbol' },
timestamp: { $timestamp: { t: 0, i: 0 } }
Expand Down Expand Up @@ -237,7 +280,9 @@ describe('Extended JSON', function() {
// minKey
expect(result.minKey).to.be.an.instanceOf(BSON.MinKey);
// objectID
expect(result.objectId.toString()).to.equal('111111111111111111111111');
expect(result.objectID.toString()).to.equal('111111111111111111111111');
expect(result.oldObjectID.toString()).to.equal('111111111111111111111111');
//bsonRegExp
expect(result.bsonRegExp).to.be.an.instanceOf(BSON.BSONRegExp);
expect(result.bsonRegExp.pattern).to.equal('hello world');
Expand Down

0 comments on commit ba98ccb

Please sign in to comment.