Skip to content

Commit

Permalink
feat(NODE-4789): support Map stringification in EJSON (#567)
Browse files Browse the repository at this point in the history
  • Loading branch information
W-A-James authored Mar 16, 2023
1 parent 24c6a9c commit c70c82d
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 1 deletion.
14 changes: 13 additions & 1 deletion src/extended_json.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { Long } from './long';
import { MaxKey } from './max_key';
import { MinKey } from './min_key';
import { ObjectId } from './objectid';
import { isDate, isRegExp } from './parser/utils';
import { isDate, isRegExp, isMap } from './parser/utils';
import { BSONRegExp } from './regexp';
import { BSONSymbol } from './symbol';
import { Timestamp } from './timestamp';
Expand Down Expand Up @@ -190,6 +190,18 @@ function getISOString(date: Date) {

// eslint-disable-next-line @typescript-eslint/no-explicit-any
function serializeValue(value: any, options: EJSONSerializeOptions): any {
if (value instanceof Map || isMap(value)) {
const obj: Record<string, unknown> = Object.create(null);
for (const [k, v] of value) {
if (typeof k !== 'string') {
throw new BSONError('Can only serialize maps with string keys');
}
obj[k] = v;
}

return serializeValue(obj, options);
}

if ((typeof value === 'object' || typeof value === 'function') && value !== null) {
const index = options.seenObjects.findIndex(entry => entry.obj === value);
if (index !== -1) {
Expand Down
39 changes: 39 additions & 0 deletions test/node/extended_json.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ const EJSON = BSON.EJSON;
import * as vm from 'node:vm';
import { expect } from 'chai';
import { BSONVersionError, BSONRuntimeError } from '../../src';
import { BSONError } from '../register-bson';

// BSON types
const Binary = BSON.Binary;
Expand Down Expand Up @@ -583,4 +584,42 @@ describe('Extended JSON', function () {
})
).to.throw(BSONVersionError, /Unsupported BSON version/i);
});

context('Map objects', function () {
it('serializes an empty Map object', () => {
const input = new Map();
expect(EJSON.stringify(input)).to.equal('{}');
});

it('serializes a nested Map object', () => {
const input = new Map([
[
'a',
new Map([
['a', 100],
['b', 200]
])
]
]);

const str = EJSON.stringify(input);
expect(str).to.equal('{"a":{"a":100,"b":200}}');
});

it('serializes a Map with one string key', () => {
const input = new Map([['a', 100]]);

const str = EJSON.stringify(input);
expect(str).to.equal('{"a":100}');
});

it('throws BSONError when passed Map object with non-string keys', () => {
const input: Map<number, unknown> = new Map([
[1, 100],
[2, 200]
]);

expect(() => EJSON.stringify(input)).to.throw(BSONError);
});
});
});

0 comments on commit c70c82d

Please sign in to comment.