diff --git a/lib/binary.js b/lib/binary.js index 3cb41757..b3d872c2 100644 --- a/lib/binary.js +++ b/lib/binary.js @@ -274,6 +274,32 @@ class Binary { toString(format) { return this.buffer != null ? this.buffer.slice(0, this.position).toString(format) : ''; } + + /** + * @ignore + */ + toExtendedJSON() { + const base64String = Buffer.isBuffer(this.buffer) + ? this.buffer.toString('base64') + : Buffer.from(this.buffer).toString('base64'); + + const subType = Number(this.sub_type).toString(16); + return { + $binary: { + base64: base64String, + subType: subType.length === 1 ? '0' + subType : subType + } + }; + } + + /** + * @ignore + */ + static fromExtendedJSON(doc) { + const type = doc.$binary.subType ? parseInt(doc.$binary.subType, 16) : 0; + const data = new Buffer(doc.$binary.base64, 'base64'); + return new Binary(data, type); + } } /** diff --git a/lib/code.js b/lib/code.js index 1db9089b..21a9cc08 100644 --- a/lib/code.js +++ b/lib/code.js @@ -22,6 +22,24 @@ class Code { toJSON() { return { scope: this.scope, code: this.code }; } + + /** + * @ignore + */ + toExtendedJSON() { + if (this.scope) { + return { $code: this.code, $scope: this.scope }; + } + + return { $code: this.code }; + } + + /** + * @ignore + */ + static fromExtendedJSON(doc) { + return new Code(doc.$code, doc.$scope); + } } Object.defineProperty(Code.prototype, '_bsontype', { value: 'Code' }); diff --git a/lib/db_ref.js b/lib/db_ref.js index f1d5f716..77633491 100644 --- a/lib/db_ref.js +++ b/lib/db_ref.js @@ -42,6 +42,29 @@ class DBRef { if (this.db != null) o.$db = this.db; return o; } + + /** + * @ignore + */ + toExtendedJSON() { + let o = { + $ref: this.collection, + $id: this.oid + }; + + if (this.db) o.$db = this.db; + o = Object.assign(o, this.fields); + return o; + } + + /** + * @ignore + */ + static fromExtendedJSON(doc) { + var copy = Object.assign({}, doc); + ['$ref', '$id', '$db'].forEach(k => delete copy[k]); + return new DBRef(doc.$ref, doc.$id, doc.$db, copy); + } } Object.defineProperty(DBRef.prototype, '_bsontype', { value: 'DBRef' }); diff --git a/lib/decimal128.js b/lib/decimal128.js index 3e2a5716..d4a285c6 100644 --- a/lib/decimal128.js +++ b/lib/decimal128.js @@ -788,5 +788,19 @@ Decimal128.prototype.toJSON = function() { return { $numberDecimal: this.toString() }; }; +/** + * @ignore + */ +Decimal128.prototype.toExtendedJSON = function() { + return { $numberDecimal: this.toString() }; +}; + +/** + * @ignore + */ +Decimal128.fromExtendedJSON = function(doc) { + return Decimal128.fromString(doc.$numberDecimal); +}; + Object.defineProperty(Decimal128.prototype, '_bsontype', { value: 'Decimal128' }); module.exports = Decimal128; diff --git a/lib/double.js b/lib/double.js index ae28390d..03f9e405 100644 --- a/lib/double.js +++ b/lib/double.js @@ -29,6 +29,23 @@ class Double { toJSON() { return this.value; } + + /** + * @ignore + */ + toExtendedJSON(options) { + if (options && options.relaxed && isFinite(this.value)) return this.value; + return { $numberDouble: this.value.toString() }; + } + + /** + * @ignore + */ + static fromExtendedJSON(doc, options) { + return options && options.relaxed + ? parseFloat(doc.$numberDouble) + : new Double(parseFloat(doc.$numberDouble)); + } } Object.defineProperty(Double.prototype, '_bsontype', { value: 'Double' }); diff --git a/lib/int_32.js b/lib/int_32.js index 1f064691..5ef5f95a 100644 --- a/lib/int_32.js +++ b/lib/int_32.js @@ -29,6 +29,21 @@ class Int32 { toJSON() { return this.value; } + + /** + * @ignore + */ + toExtendedJSON(options) { + if (options && options.relaxed) return this.value; + return { $numberInt: this.value.toString() }; + } + + /** + * @ignore + */ + static fromExtendedJSON(doc, options) { + return options && options.relaxed ? parseInt(doc.$numberInt, 10) : new Int32(doc.$numberInt); + } } Object.defineProperty(Int32.prototype, '_bsontype', { value: 'Int32' }); diff --git a/lib/long.js b/lib/long.js index dc5a5826..c9f9f833 100644 --- a/lib/long.js +++ b/lib/long.js @@ -1,5 +1,21 @@ 'use strict'; const Long = require('long'); +/** + * @ignore + */ +Long.prototype.toExtendedJSON = function(options) { + if (options && options.relaxed) return this.toNumber(); + return { $numberLong: this.toString() }; +}; + +/** + * @ignore + */ +Long.fromExtendedJSON = function(doc, options) { + const result = Long.fromString(doc.$numberLong); + return options && options.relaxed ? result.toNumber() : result; +}; + Object.defineProperty(Long.prototype, '_bsontype', { value: 'Long' }); module.exports = Long; diff --git a/lib/max_key.js b/lib/max_key.js index 0b97a41e..b308c77a 100644 --- a/lib/max_key.js +++ b/lib/max_key.js @@ -9,6 +9,20 @@ class MaxKey { * @return {MaxKey} A MaxKey instance */ constructor() {} + + /** + * @ignore + */ + toExtendedJSON() { + return { $maxKey: 1 }; + } + + /** + * @ignore + */ + static fromExtendedJSON() { + return new MaxKey(); + } } Object.defineProperty(MaxKey.prototype, '_bsontype', { value: 'MaxKey' }); diff --git a/lib/min_key.js b/lib/min_key.js index f4c59f7e..add6bd12 100644 --- a/lib/min_key.js +++ b/lib/min_key.js @@ -9,6 +9,20 @@ class MinKey { * @return {MinKey} A MinKey instance */ constructor() {} + + /** + * @ignore + */ + toExtendedJSON() { + return { $minKey: 1 }; + } + + /** + * @ignore + */ + static fromExtendedJSON() { + return new MinKey(); + } } Object.defineProperty(MinKey.prototype, '_bsontype', { value: 'MinKey' }); diff --git a/lib/objectid.js b/lib/objectid.js index 4d28c9e8..e83d09ae 100644 --- a/lib/objectid.js +++ b/lib/objectid.js @@ -351,6 +351,21 @@ class ObjectId { return false; } + + /** + * @ignore + */ + toExtendedJSON() { + if (this.toHexString) return { $oid: this.toHexString() }; + return { $oid: this.toString('hex') }; + } + + /** + * @ignore + */ + static fromExtendedJSON(doc) { + return new ObjectId(doc.$oid); + } } /** diff --git a/lib/regexp.js b/lib/regexp.js index ab6ff36a..ac8c2355 100644 --- a/lib/regexp.js +++ b/lib/regexp.js @@ -38,6 +38,26 @@ class BSONRegExp { } } } + + /** + * @ignore + */ + toExtendedJSON() { + return { $regularExpression: { pattern: this.pattern, options: this.options } }; + } + + /** + * @ignore + */ + static fromExtendedJSON(doc) { + return new BSONRegExp( + doc.$regularExpression.pattern, + doc.$regularExpression.options + .split('') + .sort() + .join('') + ); + } } Object.defineProperty(BSONRegExp.prototype, '_bsontype', { value: 'BSONRegExp' }); diff --git a/lib/symbol.js b/lib/symbol.js index 060d3d0e..8bd975e6 100644 --- a/lib/symbol.js +++ b/lib/symbol.js @@ -42,6 +42,20 @@ class Symbol { toJSON() { return this.value; } + + /** + * @ignore + */ + toExtendedJSON() { + return { $symbol: this.value }; + } + + /** + * @ignore + */ + static fromExtendedJSON(doc) { + return new Symbol(doc.$symbol); + } } Object.defineProperty(Symbol.prototype, '_bsontype', { value: 'Symbol' }); diff --git a/lib/timestamp.js b/lib/timestamp.js index 6d88a2ad..9b5249e1 100644 --- a/lib/timestamp.js +++ b/lib/timestamp.js @@ -74,6 +74,20 @@ class Timestamp extends Long { static fromString(str, opt_radix) { return new Timestamp(Long.fromString(str, opt_radix)); } + + /** + * @ignore + */ + toExtendedJSON() { + return { $timestamp: { t: this.high, i: this.low } }; + } + + /** + * @ignore + */ + static fromExtendedJSON(doc) { + return new Timestamp(doc.$timestamp.i, doc.$timestamp.t); + } } Object.defineProperty(Timestamp.prototype, '_bsontype', { value: 'Timestamp' });