private function getDirtyFields(
        array $newSerializedModel,
        array $oldSerializedModel,
        ClassMetadata $classMetadata
    ): array {
        $dirtyFields = [];

        foreach ($newSerializedModel as $key => $value) {
            if (!array_key_exists($key, $oldSerializedModel)) {
                // a new key has been found, add it to the dirtyFields
                $dirtyFields[$key] = $value;
                continue;
            }

            $oldValue = $oldSerializedModel[$key];

            $currentRelation = $classMetadata->getRelation($key);

            if (!$currentRelation) {
                if (
                    is_array($value) &&
                    !ArrayHelper::arraySame($value, $oldValue ?: []) ||
                    $value !== $oldValue
                ) {
                    $dirtyFields[$key] = $value;
                }
                continue;
            }

            $currentClassMetadata = $this->mapping->getClassMetadata(
                $currentRelation->getTargetEntity()
            );

            $idSerializedKey = $currentClassMetadata->getIdSerializeKey();

            if (Relation::MANY_TO_ONE === $currentRelation->getType()) {
                if ($value !== $oldValue) {
                    if (is_string($value) || is_string($oldValue)) {
                        $dirtyFields[$key] = $value;
                    } else {
                        $recursiveDiff = $this->getDirtyFields(
                            $value,
                            $oldValue,
                            $currentClassMetadata
                        );

                        if (!empty($recursiveDiff)) {
                            $recursiveDiff[
                                $idSerializedKey
                            ] = self::getEntityId($value, $idSerializedKey);
                            $dirtyFields[$key] = $recursiveDiff;
                        }
                    }
                }

                continue;
            }

            // ONE_TO_MANY relation
            if (count($value ?? []) !== count($oldValue ?? [])) {
                // get all objects ids of new array
                $dirtyFields[$key] = $this->addIdentifiers(
                    $value,
                    [],
                    $idSerializedKey
                );
            }

            if (!empty($value)) {
                foreach ($value as $relationKey => $relationValue) {
                    $oldRelationValue = $this->findOldRelation(
                        $relationValue,
                        $oldValue,
                        $currentClassMetadata
                    );

                    if ($relationValue !== $oldRelationValue) {
                        if (
                            is_string($relationValue) ||
                            is_string($oldRelationValue)
                        ) {
                            $dirtyFields[$key][$relationKey] = $relationValue;
                        } else {
                            $recursiveDiff = $this->getDirtyFields(
                                $relationValue,
                                $oldRelationValue,
                                $currentClassMetadata
                            );

                            if (!empty($recursiveDiff)) {
                                $idSerializedKey = $currentClassMetadata->getIdSerializeKey();

                                $entityId = self::getEntityId(
                                    $relationValue,
                                    $idSerializedKey
                                );
                                if (null !== $entityId) {
                                    $recursiveDiff[
                                        $idSerializedKey
                                    ] = $entityId;
                                }
                                $dirtyFields[$key][
                                    $relationKey
                                ] = $recursiveDiff;
                            }
                        }
                    }
                }
            }
        }

        return $dirtyFields;
    }