title: API Platform: Denormalization serialization for nested data with custom identifier (NOT the entity primary key)
body: <p>How to use a custom identifier (not the primary key) on denormalization for nested data?</p>
  
  <p>I am already using Groups for nested data, in order to normalize/denormalize my resource.</p>
  
  <p>I have the below JSON which is used to create an: </p>
  
  <ul>
  <li>invoice 
  
  <ul>
  <li>invoiceLine
  
  <ul>
  <li>item</li>
  </ul></li>
  </ul></li>
  </ul>
  
  <pre><code>{
      "total": "1060.000",
      "paid": "1100.000",
      "status": true,
      "invoiceLine": [
          {
              "price": "460.000",
              "quantity": 1,
              "item": {
                  "clientItemId": 9,
                  "name": "laptop",
                  "price": "13000",
                  "category": "/categories/2"
              }
          },
          {
              "price": "600.000",
              "quantity": 2,
              "item": {
                  "clientItemId": 10,
                  "name": "screen",
                  "price": "300.000",
                  "category": "/categories/2"
              }
          }
      ]
  }
  </code></pre>
  
  <p>How can I make sure that items are not always created (duplicated), using the <code>clientItemId</code> instead of the entity <code>id</code>?</p>
  
  <blockquote>
    <p>Note: that I can not use <code>clientItemId</code> as my primary key since I have different clients, and 2 clients might have the same value for <code>clientItemId</code> (think of it as a unique ref. code given by the client), that is why I have my own generated value <code>id</code>.</p>
  </blockquote>
  
  <h2>Entity Classes</h2>
  
  <h3>api/src/Entity/InvoiceLine.php</h3>
  
  <pre><code>&lt;?php
  
  namespace App\Entity;
  
  use ApiPlatform\Core\Annotation\ApiResource;
  use Symfony\Component\Serializer\Annotation\Groups;
  use Symfony\Component\Validator\Constraints as Assert;
  use Doctrine\ORM\Mapping as ORM;
  
  /**
   * @ApiResource()
   * @ORM\Entity(repositoryClass="App\Repository\InvoiceLineRepository")
   */
  class InvoiceLine
  {
      /**
       * @ORM\Id()
       * @ORM\GeneratedValue()
       * @ORM\Column(type="integer")
       *
       * @Groups({"order"})
       */
      private $id;
  
      /**
       * @ORM\Column(type="decimal", precision=15, scale=2)
       *
       * @Groups({"order"})
       */
      private $price;
  
      /**
       * @ORM\Column(type="integer")
       *
       * @Groups({"order"})
       */
      private $quantity;
  
      /**
       * @ORM\ManyToOne(
       *     targetEntity="App\Entity\Invoice",
       *     inversedBy="InvoiceLines"
       * )
       * @ORM\JoinColumn(nullable=false)
       */
      private $invoice;
  
      /**
       * @ORM\ManyToOne(
       *     targetEntity="App\Entity\Item",
       *     cascade={"persist"}
       * )
       * @ORM\JoinColumn(nullable=false)
       *
       * @Groups({"order"})
       */
      private $item;
  ...
  </code></pre>
  
  <h3>api/src/Entity/Item.php</h3>
  
  <pre><code>&lt;?php
  
  namespace App\Entity;
  
  use ApiPlatform\Core\Annotation\ApiResource;
  use ApiPlatform\Core\Annotation\ApiSubresource;
  use ApiPlatform\Core\Annotation\ApiProperty;
  use Symfony\Component\Serializer\Annotation\Groups;
  use Doctrine\ORM\Mapping as ORM;
  
  /**
   * @ApiResource()
   * @ORM\Entity(repositoryClass="App\Repository\ItemRepository")
   */
  class Item
  {
      /**
       * @ORM\Id()
       * @ORM\GeneratedValue()
       * @ORM\Column(type="integer")
       *
       * @Groups({"order"})
       */
      private $id;
  
      /**
       * @ORM\Column(type="integer", nullable=true)
       *
       * @Groups({"order"})
       */
      private $clientItemId;
  
      /**
       * @ORM\Column(type="string", length=255)
       *
       * @Groups({"order"})
       */
      private $name;
  
      /**
       * @ORM\Column(type="decimal", precision=15, scale=3)
       *
       * @Groups({"order"})
       */
      private $price;
  
      /**
       * @ORM\ManyToOne(targetEntity="App\Entity\ItemCategory", inversedBy="Items")
       * @ORM\JoinColumn(nullable=false)
       *
       * @Groups({"order"})
       */
      private $ItemCategory;
  ...
  </code></pre>