From 7409e6b3117c7885edbb60911e47e4e8475accab Mon Sep 17 00:00:00 2001 From: Lumi Pakkanen Date: Mon, 13 May 2024 16:22:46 +0300 Subject: [PATCH] JSON serialize NaN and Infinity ref #318 --- src/__tests__/monzo.spec.ts | 16 +++++++++++++--- src/monzo.ts | 26 ++++++++++++++++++++++++-- 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/__tests__/monzo.spec.ts b/src/__tests__/monzo.spec.ts index 7a05f2cb..6f344346 100644 --- a/src/__tests__/monzo.spec.ts +++ b/src/__tests__/monzo.spec.ts @@ -461,16 +461,18 @@ describe('JSON serialization', () => { 3.5, TimeMonzo.fromFraction('81/80'), null, + new TimeReal(0, NaN), + new TimeReal(1, Infinity), ]; const serialized = JSON.stringify(data); expect(serialized).toBe( - '["Hello, world!",{"n":10,"d":7},{"type":"TimeReal","timeExponent":-1,"value":777},3.5,{"type":"TimeMonzo","timeExponent":{"n":0,"d":1},"primeExponents":[{"n":-4,"d":1},{"n":4,"d":1},{"n":-1,"d":1},{"n":0,"d":1},{"n":0,"d":1},{"n":0,"d":1},{"n":0,"d":1},{"n":0,"d":1},{"n":0,"d":1}],"residual":{"n":1,"d":1}},null]' + '["Hello, world!",{"n":10,"d":7},{"type":"TimeReal","timeExponent":-1,"value":777},3.5,{"type":"TimeMonzo","timeExponent":{"n":0,"d":1},"primeExponents":[{"n":-4,"d":1},{"n":4,"d":1},{"n":-1,"d":1},{"n":0,"d":1},{"n":0,"d":1},{"n":0,"d":1},{"n":0,"d":1},{"n":0,"d":1},{"n":0,"d":1}],"residual":{"n":1,"d":1}},null,{"type":"TimeReal","timeExponent":0,"value":"NaN"},{"type":"TimeReal","timeExponent":1,"value":"Infinity"}]' ); }); it('can deserialize an array of primitives, fractions and monzos', () => { const serialized = - '["Hello, world!",{"n":10,"d":7},{"type":"TimeReal","timeExponent":-1,"value":777},3.5,{"type":"TimeMonzo","timeExponent":{"n":0,"d":1},"primeExponents":[{"n":-4,"d":1},{"n":4,"d":1},{"n":-1,"d":1},{"n":0,"d":1},{"n":0,"d":1},{"n":0,"d":1},{"n":0,"d":1},{"n":0,"d":1},{"n":0,"d":1}],"residual":{"n":1,"d":1}},null]'; + '["Hello, world!",{"n":10,"d":7},{"type":"TimeReal","timeExponent":-1,"value":777},3.5,{"type":"TimeMonzo","timeExponent":{"n":0,"d":1},"primeExponents":[{"n":-4,"d":1},{"n":4,"d":1},{"n":-1,"d":1},{"n":0,"d":1},{"n":0,"d":1},{"n":0,"d":1},{"n":0,"d":1},{"n":0,"d":1},{"n":0,"d":1}],"residual":{"n":1,"d":1}},null,{"type":"TimeReal","timeExponent":0,"value":"NaN"},{"type":"TimeReal","timeExponent":1,"value":"Infinity"}]'; function reviver(key: string, value: any) { return TimeMonzo.reviver( key, @@ -478,7 +480,7 @@ describe('JSON serialization', () => { ); } const data = JSON.parse(serialized, reviver); - expect(data).toHaveLength(6); + expect(data).toHaveLength(8); expect(data[0]).toBe('Hello, world!'); @@ -495,5 +497,13 @@ describe('JSON serialization', () => { expect(data[4].toFraction().toFraction()).toBe('81/80'); expect(data[5]).toBeNull(); + + expect(data[6]).toBeInstanceOf(TimeReal); + expect(data[6].timeExponent).toBe(0); + expect(data[6].value).toBeNaN(); + + expect(data[7]).toBeInstanceOf(TimeReal); + expect(data[7].timeExponent).toBe(1); + expect(data[7].value).toBe(Infinity); }); }); diff --git a/src/monzo.ts b/src/monzo.ts index 25dd03bd..cf071867 100644 --- a/src/monzo.ts +++ b/src/monzo.ts @@ -184,6 +184,10 @@ export class TimeReal { if (!value) { timeExponent = 0; } + // Checks for Infinity and NaN + if (!isFinite(timeExponent)) { + throw new Error('Time exponent must be finite.'); + } this.timeExponent = timeExponent; this.value = value; } @@ -233,7 +237,15 @@ export class TimeReal { value !== null && value.type === 'TimeReal' ) { - return new TimeReal(value.timeExponent, value.value); + let v: number | string = value.value; + if (v === 'NaN') { + v = NaN; + } else if (v === 'Infinity') { + v = Infinity; + } else if (v === '-Infinity') { + v = -Infinity; + } + return new TimeReal(value.timeExponent, v as number); } return value; } @@ -243,10 +255,20 @@ export class TimeReal { * @returns The serialized object with property `type` set to `'TimeReal'`. */ toJSON() { + let value: number | string = this.value; + // JSON sure is a standard + if (isNaN(value)) { + value = 'NaN'; + } else if (value === Infinity) { + value = 'Infinity'; + } else if (value === -Infinity) { + value = '-Infinity'; + } + return { type: 'TimeReal', timeExponent: this.timeExponent, - value: this.value, + value, }; }