Skip to content

Commit 3a16117

Browse files
committed
feat: add toEJSON API to element
1 parent 640e2ff commit 3a16117

File tree

2 files changed

+101
-2
lines changed

2 files changed

+101
-2
lines changed

packages/hadron-document/src/element.ts

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,13 @@ import Events from './element-events';
1111
import type Document from './document';
1212
import type { TypeCastTypes } from 'hadron-type-checker';
1313
import type { Binary, ObjectId } from 'bson';
14-
import type { BSONArray, BSONObject, BSONValue } from './utils';
15-
import { getDefaultValueForType } from './utils';
14+
import type {
15+
BSONArray,
16+
BSONObject,
17+
BSONValue,
18+
HadronEJSONOptions,
19+
} from './utils';
20+
import { getDefaultValueForType, objectToIdiomaticEJSON } from './utils';
1621
import { DocumentEvents, ElementEvents } from '.';
1722

1823
export const DATE_FORMAT = 'YYYY-MM-DD HH:mm:ss.SSS';
@@ -292,6 +297,22 @@ export class Element extends EventEmitter {
292297
return this.value;
293298
}
294299

300+
/**
301+
* Generate the Extended JSON string representation of this element.
302+
*
303+
* @returns The Extended JSON string.
304+
*/
305+
toEJSON(
306+
source: 'original' | 'current' = 'current',
307+
options: HadronEJSONOptions = {}
308+
): string {
309+
const generated =
310+
source === 'original'
311+
? this.generateOriginalObject()
312+
: this.generateObject();
313+
return objectToIdiomaticEJSON(generated, options);
314+
}
315+
295316
/**
296317
* Insert an element after the provided element. If this element is an array,
297318
* then ignore the key specified by the caller and use the correct index.

packages/hadron-document/test/element.test.ts

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3038,4 +3038,82 @@ describe('Element', function () {
30383038
});
30393039
}
30403040
);
3041+
3042+
describe('#toEJSON', function () {
3043+
it('handles null values', function () {
3044+
const element = new Element('test', {
3045+
a: 1,
3046+
b: { foo: 2 },
3047+
null_val: null,
3048+
});
3049+
expect(element.toEJSON('current', { indent: undefined })).to.equal(
3050+
'{"a":1,"b":{"foo":2},"null_val":null}'
3051+
);
3052+
});
3053+
3054+
it('serializes Int32/Double as relaxed but not Int64', function () {
3055+
const element = new Element('test', {
3056+
a: 1,
3057+
b: 1.5,
3058+
c: Long.fromNumber(2),
3059+
});
3060+
expect(element.toEJSON('current', { indent: undefined })).to.equal(
3061+
'{"a":1,"b":1.5,"c":{"$numberLong":"2"}}'
3062+
);
3063+
});
3064+
3065+
it('serializes Date as relaxed, but not dates before 1970 and after 9999', function () {
3066+
const element = new Element('test', {
3067+
epoch: new Date(0),
3068+
negative: new Date(-1),
3069+
y10k: new Date(253402300800000),
3070+
});
3071+
expect(element.toEJSON('current', { indent: undefined })).to.equal(
3072+
'{"epoch":{"$date":"1970-01-01T00:00:00.000Z"},"negative":{"$date":{"$numberLong":"-1"}},"y10k":{"$date":{"$numberLong":"253402300800000"}}}'
3073+
);
3074+
});
3075+
3076+
it('optionally serializes the current or the original element', function () {
3077+
const element = new Element('test', {
3078+
a: 1,
3079+
b: 1.5,
3080+
c: Long.fromNumber(2),
3081+
});
3082+
element.get('a')?.edit(new Int32(2));
3083+
expect(element.toEJSON('current', { indent: undefined })).to.equal(
3084+
'{"a":2,"b":1.5,"c":{"$numberLong":"2"}}'
3085+
);
3086+
expect(element.toEJSON('original', { indent: undefined })).to.equal(
3087+
'{"a":1,"b":1.5,"c":{"$numberLong":"2"}}'
3088+
);
3089+
});
3090+
3091+
it('allows specifying JSON indent', function () {
3092+
const element = new Element('test', { a: 1 });
3093+
expect(element.toEJSON('current', { indent: '>' })).to.equal(
3094+
'{\n>"a": 1\n}'
3095+
);
3096+
});
3097+
3098+
it('handles oddball floating point values', function () {
3099+
const element = new Element('test', {
3100+
negzero: new Double(-0),
3101+
int: new Int32(1),
3102+
inf: Infinity,
3103+
ninf: -Infinity,
3104+
nan: NaN,
3105+
});
3106+
expect(element.toEJSON('current', { indent: undefined })).to.equal(
3107+
'{' +
3108+
[
3109+
'"negzero":{"$numberDouble":"-0.0"},',
3110+
'"int":1,',
3111+
'"inf":{"$numberDouble":"Infinity"},',
3112+
'"ninf":{"$numberDouble":"-Infinity"},',
3113+
'"nan":{"$numberDouble":"NaN"}',
3114+
].join('') +
3115+
'}'
3116+
);
3117+
});
3118+
});
30413119
});

0 commit comments

Comments
 (0)