diff --git a/src/Metadata/MetadataFactory.php b/src/Metadata/MetadataFactory.php
index 086c03f80d2f2a5231b59e5bd7647c263c669c13..7795cdee8032b629c9fab5cd67e9099d4d6c02c8 100644
--- a/src/Metadata/MetadataFactory.php
+++ b/src/Metadata/MetadataFactory.php
@@ -358,6 +358,7 @@ final class MetadataFactory implements MetadataFactoryInterface
             $mode = PropertyMetadataFactory::MODE_OTHER;
         }
         $propertyMetadataFactory = new PropertyMetadataFactory(
+            $this->resourceClassResolver,
             $this->propertyNameCollectionFactory,
             $this->propertyMetadataFactory,
             $class,
@@ -418,12 +419,15 @@ final class MetadataFactory implements MetadataFactoryInterface
      * @param OperationDef|null $opDef
      * @param array             $groups
      *
-     * @throws \ApiPlatform\Core\Exception\ResourceClassNotFoundException
-     *
      * @return string
      */
-    private function getRepresentationName(ClassName $root, ClassName $class, bool $normalization, ?OperationDef $opDef, array $groups): string
-    {
+    private function getRepresentationName(
+        ClassName $root,
+        ClassName $class,
+        bool $normalization,
+        ?OperationDef $opDef,
+        array $groups
+    ): string {
         if ($normalization && (!$groups || $groups === $this->getDefaultGroups($class))) {
             return $class->getBaseName();
         }
diff --git a/src/Metadata/PropertyMetadata.php b/src/Metadata/PropertyMetadata.php
index e86def00bf11be1509d5071ea42bd28ba0828d93..3ba802bd7eb6247acbb74f40e90f11ceb4162080 100644
--- a/src/Metadata/PropertyMetadata.php
+++ b/src/Metadata/PropertyMetadata.php
@@ -54,6 +54,9 @@ class PropertyMetadata implements \JsonSerializable, HasName
     /** @var bool */
     private $embedded;
 
+    /** @var bool */
+    private $nullable;
+
     /**
      * PropertyMetadata constructor.
      *
@@ -72,6 +75,7 @@ class PropertyMetadata implements \JsonSerializable, HasName
         string $description,
         Type $type,
         bool $identifier,
+        bool $nullable,
         bool $readable,
         bool $writable,
         bool $initializable,
@@ -82,11 +86,12 @@ class PropertyMetadata implements \JsonSerializable, HasName
         $this->description = $description;
         $this->type = $type;
         $this->identifier = $identifier;
+        $this->nullable = $nullable;
         $this->readable = $readable;
         $this->writable = $writable;
         $this->initializable = $initializable;
         $this->link = $link;
-        $this->embedded = $embedded;
+        $this->embedded = $link;
     }
 
     /**
@@ -167,7 +172,7 @@ class PropertyMetadata implements \JsonSerializable, HasName
      */
     public function isNullable(): bool
     {
-        return $this->type ? $this->type->isNullable() : true;
+        return $this->nullable;
     }
 
     /**
diff --git a/src/Metadata/PropertyMetadataFactory.php b/src/Metadata/PropertyMetadataFactory.php
index 1c2c1bb18b583bc62ec26ed4ba84f4a80af90716..a6acda8093e9a343e907b04dc7e0c42b347d0374 100644
--- a/src/Metadata/PropertyMetadataFactory.php
+++ b/src/Metadata/PropertyMetadataFactory.php
@@ -19,6 +19,7 @@
 
 namespace Irstea\NgModelGeneratorBundle\Metadata;
 
+use ApiPlatform\Core\Api\ResourceClassResolverInterface;
 use ApiPlatform\Core\Exception\ResourceClassNotFoundException;
 use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface;
 use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface;
@@ -37,16 +38,6 @@ class PropertyMetadataFactory
     public const MODE_READ = 'READ';
     public const MODE_OTHER = 'OTHER';
 
-    /**
-     * Mode des objets relatifs en fonction du mode de la resource.
-     */
-    private const RELATED_MODES = [
-        self::MODE_CREATE => self::MODE_UPDATE,
-        self::MODE_UPDATE => self::MODE_UPDATE,
-        self::MODE_READ   => self::MODE_READ,
-        self::MODE_OTHER  => self::MODE_OTHER,
-    ];
-
     /** @var PropertyNameCollectionFactoryInterface */
     private $propertyNameCollectionFactory;
 
@@ -68,9 +59,13 @@ class PropertyMetadataFactory
     /** @var array */
     private $properties = [];
 
+    /** @var ResourceClassResolverInterface */
+    private $resourceClassResolver;
+
     /**
      * PropertyMetadataFactory constructor.
      *
+     * @param ResourceClassResolverInterface         $resourceClassResolver
      * @param PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory
      * @param PropertyMetadataFactoryInterface       $propertyMetadataFactory
      * @param ClassName                              $resource
@@ -78,6 +73,7 @@ class PropertyMetadataFactory
      * @param array                                  $groups
      */
     public function __construct(
+        ResourceClassResolverInterface $resourceClassResolver,
         PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory,
         PropertyMetadataFactoryInterface $propertyMetadataFactory,
         ClassName $resource,
@@ -89,6 +85,7 @@ class PropertyMetadataFactory
         $this->resource = $resource;
         $this->mode = $mode;
         $this->groups = $groups;
+        $this->resourceClassResolver = $resourceClassResolver;
     }
 
     /**
@@ -105,63 +102,72 @@ class PropertyMetadataFactory
         $typeMeta = $propertyMeta->getType();
         \assert($typeMeta !== null);
 
-        $mode = $this->getMode($class);
-        $link = $embedded = $mode === self::MODE_READ ? $propertyMeta->isReadableLink() : $propertyMeta->isWritableLink();
-
-        if (!$embedded) {
-            $leafType = $this->getLeafType($typeMeta);
-            $leafClass = $leafType ? $leafType->getClassName() : null;
-            if ($leafClass) {
-                try {
-                    $leafProperties = $this->getAPIMetadata(PHPClass::get($leafClass));
-                    $embedded = \count($leafProperties) > 0;
-                    $link = true;
-                } catch (ResourceClassNotFoundException $ex) {
-                    // NOOP
-                }
-            }
-        }
+        [$link, $embedded] = $this->getLinkStatus($propertyMeta);
+
+        $nullable = $this->mode === self::MODE_UPDATE || $typeMeta->isNullable();
 
         return new PropertyMetadata(
             $propertyName,
             '',
             $typeMeta,
             $propertyMeta->isIdentifier(),
+            $nullable,
             $propertyMeta->isReadable(),
             $propertyMeta->isWritable(),
-            $propertyMeta->isInitializable() ?: false,
-            $link ?: false,
-            $embedded ?: false
+            (bool) $propertyMeta->isInitializable(),
+            $link,
+            $embedded
         );
     }
 
     /**
-     * @param Type $type
+     * @param $propertyMeta
      *
-     * @return Type|null
+     * @return array
      */
-    private function getLeafType(Type $type): ?Type
+    private function getLinkStatus(APIPropertyMetadata $propertyMeta): array
     {
-        while ($type && $type->isCollection()) {
-            $type = $type->getCollectionValueType();
+        $typeMeta = $propertyMeta->getType();
+        \assert($typeMeta !== null);
+
+        $leafType = $this->getLeafType($typeMeta);
+        if (!$leafType) {
+            return [false, false];
         }
 
-        return $type;
+        $leafClassName = $leafType->getClassName();
+        if (!$leafClassName || !$this->resourceClassResolver->isResourceClass($leafClassName)) {
+            return [false, false];
+        }
+
+        $leafClass = PHPClass::get($leafClassName);
+        $embedded = $this->mode === self::MODE_READ ? $propertyMeta->isReadableLink() : $propertyMeta->isWritableLink();
+
+        if (!\is_bool($embedded)) {
+            $leafProperties = $this->getAPIMetadata($leafClass);
+            foreach ($leafProperties as $leafProperty) {
+                if (!$leafProperty->isIdentifier()) {
+                    $embedded = true;
+                    break;
+                }
+            }
+        }
+
+        return [true, (bool) $embedded];
     }
 
     /**
-     * @param ClassName $class
+     * @param Type $type
      *
-     * @return string
+     * @return Type|null
      */
-    private function getMode(ClassName $class): string
+    private function getLeafType(Type $type): ?Type
     {
-        $mode = $this->mode;
-        if ($class->getFullName() === $this->resource->getFullName()) {
-            $mode = self::RELATED_MODES[$mode];
+        while ($type && $type->isCollection()) {
+            $type = $type->getCollectionValueType();
         }
 
-        return $mode;
+        return $type;
     }
 
     /**
@@ -192,9 +198,9 @@ class PropertyMetadataFactory
      */
     private function doGetAPIMetadata(ClassName $class): array
     {
-        $mode = $this->getMode($class);
         $properties = [];
         $options = $this->groups ? ['serializer_groups' => $this->groups] : [];
+        $isResource = $class->getFullName() === $this->resource->getFullName();
 
         foreach ($this->propertyNameCollectionFactory->create($class->getFullName(), $options) as $propertyName) {
             \assert(\is_string($propertyName));
@@ -205,7 +211,7 @@ class PropertyMetadataFactory
                 continue;
             }
 
-            if (!$this->acceptProperty($mode, $propertyMeta)) {
+            if (!$this->acceptProperty($isResource, $propertyMeta)) {
                 continue;
             }
 
@@ -218,16 +224,26 @@ class PropertyMetadataFactory
     /**
      * @param string              $mode
      * @param APIPropertyMetadata $propertyMeta
+     * @param mixed               $isResource
      *
      * @return bool
      */
-    private function acceptProperty(string $mode, APIPropertyMetadata $propertyMeta): bool
+    private function acceptProperty(bool $isResource, APIPropertyMetadata $propertyMeta): bool
     {
-        switch ($mode) {
+        if (!$isResource && $propertyMeta->isIdentifier()) {
+            return true;
+        }
+
+        switch ($this->mode) {
             case self::MODE_CREATE:
                 return $propertyMeta->isWritable() || $propertyMeta->isInitializable();
+
             case self::MODE_READ:
                 return $propertyMeta->isReadable();
+
+            case self::MODE_UPDATE:
+                return $propertyMeta->isWritable();
+
             default:
                 return $propertyMeta->isReadable() || $propertyMeta->isWritable();
         }
diff --git a/src/SerializationMapper.php b/src/SerializationMapper.php
index 0954eff82cabfa358d48043b4702283427543b59..a9ac519f5959020069d577a5555a22dedb18d9ce 100644
--- a/src/SerializationMapper.php
+++ b/src/SerializationMapper.php
@@ -303,9 +303,13 @@ final class SerializationMapper implements TypeFactoryInterface
         }
 
         if ($propertyMeta->isLink()) {
-            $type = $this->get($leafType->getClassName());
-            if (!$this->serialization->isNormalization()) {
-                $iriType = $this->createIRI([PHPClass::get($leafType->getClassName())]);
+            $leafClassName = $leafType->getClassName();
+            $type = $this->get($leafClassName);
+            $iriType = $this->createIRI([PHPClass::get($leafClassName)]);
+
+            if (!$propertyMeta->isEmbedded()) {
+                $type = $iriType;
+            } elseif (!$this->serialization->isNormalization()) {
                 $type = Union::create([$type, $iriType]);
             }
         } else {
@@ -328,7 +332,7 @@ final class SerializationMapper implements TypeFactoryInterface
             $propertyMeta->getDescription() ?: '',
             $type,
             $propertyMeta->isIdentifier(),
-            $propertyMeta->isNullable() || (!$propertyMeta->isWritable() && !$this->serialization->isNormalization()),
+            $propertyMeta->isNullable(),
             !$propertyMeta->isWritable()
         );
     }