From 1412666f75829612de6fb9d7ccae35761c9b75cb Mon Sep 17 00:00:00 2001 From: Daniel Date: Wed, 21 Dec 2022 02:57:29 +1100 Subject: [PATCH] fix: Nested objects are encoded incorrectly for MongoDB (#8209) BREAKING CHANGE: Nested objects are now properly stored in the database using JSON serialization; previously, due to a bug only top-level objects were serialized, but nested objects were saved as raw JSON; for example, a nested `Date` object was saved as a JSON object like `{ "__type": "Date", "iso": "2020-01-01T00:00:00.000Z" }` instead of its serialized representation `2020-01-01T00:00:00.000Z` (#8209) --- spec/MongoStorageAdapter.spec.js | 38 ++++++++++++++++++++ src/Adapters/Storage/Mongo/MongoTransform.js | 3 ++ 2 files changed, 41 insertions(+) diff --git a/spec/MongoStorageAdapter.spec.js b/spec/MongoStorageAdapter.spec.js index b95986140d..58731d2432 100644 --- a/spec/MongoStorageAdapter.spec.js +++ b/spec/MongoStorageAdapter.spec.js @@ -212,6 +212,44 @@ describe_only_db('mongo')('MongoStorageAdapter', () => { }); }); + it('handles nested dates', async () => { + await new Parse.Object('MyClass', { + foo: { + test: { + date: new Date(), + }, + }, + bar: { + date: new Date(), + }, + date: new Date(), + }).save(); + const adapter = Config.get(Parse.applicationId).database.adapter; + const [object] = await adapter._rawFind('MyClass', {}); + expect(object.date instanceof Date).toBeTrue(); + expect(object.bar.date instanceof Date).toBeTrue(); + expect(object.foo.test.date instanceof Date).toBeTrue(); + }); + + it('handles nested dates in array ', async () => { + await new Parse.Object('MyClass', { + foo: { + test: { + date: [new Date()], + }, + }, + bar: { + date: [new Date()], + }, + date: [new Date()], + }).save(); + const adapter = Config.get(Parse.applicationId).database.adapter; + const [object] = await adapter._rawFind('MyClass', {}); + expect(object.date[0] instanceof Date).toBeTrue(); + expect(object.bar.date[0] instanceof Date).toBeTrue(); + expect(object.foo.test.date[0] instanceof Date).toBeTrue(); + }); + it('handles updating a single object with array, object date', done => { const adapter = new MongoStorageAdapter({ uri: databaseURI }); diff --git a/src/Adapters/Storage/Mongo/MongoTransform.js b/src/Adapters/Storage/Mongo/MongoTransform.js index 91ad23fa4a..aabf744978 100644 --- a/src/Adapters/Storage/Mongo/MongoTransform.js +++ b/src/Adapters/Storage/Mongo/MongoTransform.js @@ -1014,6 +1014,9 @@ function mapValues(object, iterator) { const result = {}; Object.keys(object).forEach(key => { result[key] = iterator(object[key]); + if (result[key] && JSON.stringify(result[key]).includes(`"__type"`)) { + result[key] = mapValues(object[key], iterator); + } }); return result; }