diff --git a/packages/mikro/src/lib/serialize-entity.ts b/packages/mikro/src/lib/serialize-entity.ts index c76e576b5..ed7f78bcc 100644 --- a/packages/mikro/src/lib/serialize-entity.ts +++ b/packages/mikro/src/lib/serialize-entity.ts @@ -1,6 +1,7 @@ import { isEmpty } from '@automapper/core'; import type { AnyEntity } from '@mikro-orm/core'; import { Reference, Utils, wrap } from '@mikro-orm/core'; +import type { IWrappedEntityInternal } from '@mikro-orm/core/typings'; const excluded = [ '__gettersDefined', @@ -14,13 +15,16 @@ const excluded = [ export function serializeEntity( item: AnyEntity, itemMetadata: Record | undefined, - toPojo = false + toPojo = false, + memorized = new Map>, + skipCheckExisting = false ) { if (!Utils.isEntity(item)) return item; if (toPojo) return wrap(item).toPOJO(); const result = {} as Record; - for (const key of Reflect.ownKeys(item)) { + const keys = Object.keys((wrap(item) as IWrappedEntityInternal).__meta.properties); + for (const key of keys) { if (typeof key === 'symbol' || excluded.includes(key)) { continue; } @@ -33,6 +37,8 @@ export function serializeEntity( return serializeEntity( snapshot as AnyEntity, keyMetadata, + true, + memorized, true ); }); @@ -40,23 +46,37 @@ export function serializeEntity( } if (Reference.isReference(value)) { + const isExisting = memorized.has(value); + + if (!skipCheckExisting && isExisting) { + result[key] = memorized.get(value); + continue; + } + if (!value.isInitialized()) { + memorized.set(value, wrap(value).toPOJO()); result[key] = serializeEntity( wrap(value).toPOJO(), - keyMetadata + keyMetadata, + false, + memorized, + !isExisting ); continue; } + memorized.set(value, value.getEntity() as Record); result[key] = serializeEntity( value.getEntity(), keyMetadata, - typeof keyMetadata === 'object' && isEmpty(keyMetadata) + typeof keyMetadata === 'object' && isEmpty(keyMetadata), + memorized, + !isExisting ); continue; } - result[key] = serializeEntity(value, keyMetadata); + result[key] = serializeEntity(value, keyMetadata, false, memorized, false); } if (result['id'] == null && item['id'] != null) {