2017-02-23 4 views
0

Symfony 3を使用するJSON/JMSSerializerを介して(RESTfulな方法で)公開されるはずのエンティティを作成しました。それは次のようになります:JMSSerializer:idを使用してデータベースから関連オブジェクトを取得する

/** 
* MainEntity 
* 
* @ORM\Table(name="MainEntity") 
* @ORM\Entity 
* 
*/ 
class MainEntity{ 

    /** 
    * @var integer 
    * 
    * @ORM\Column(name="id", type="integer", nullable=false) 
    * @ORM\Id 
    * @ORM\GeneratedValue(strategy="IDENTITY") 
    */ 
    private $id; 

    //... some more "simple" fields ... 

    /** 
    * @ORM\ManyToOne(targetEntity="SubEntity") 
    * @ORM\JoinColumns({ 
    * @ORM\JoinColumn(name="subentity", referencedColumnName="id") 
    * }) 
    * @JMS\Accessor(getter="getSubEntityId",setter="setSubEntity") 
    * @JMS\Type("integer") 
    * @JMS\SerializedName("subEntityId") 
    */ 
    private $subEntity; 
    //... 

    public function getSubEntityId() { 
     return $this->subEntity->getId(); 
    } 

} 

JSONのシリアル化はすべて魅力的です!特にサブエンティティ全体ではなく、サブエンティティIDのみが公開されています。サブエンティティIDは非常に大きくなる可能性があります。

ので、代わりの

{"id": 1, ..., "subEntity": {"id": 123, "name": "Great subEntity", ...} } 

は、私は完全に私がニートものです

{"id": 1, ..., "subEntityId": 123 } 

を取得します。

しかし、それはデシリアライズに来るとき、私はトラブルに巻き込まれる... setSubEntitySubEntityインスタンスではなく数を期待するので、もちろん、私は、着信要求にも短縮JSON形式を使用したいが、これは失敗しました。

IDが与えられたときに関連オブジェクトを取得するための直列化を達成する方法はありますか?

Iは、これらの可能性について考えた:

  1. は(@JMS\Accessorアノテーションで指定された)特別なセッターを使用し、IDを取得し、データベースから検索されたオブジェクトとsubEntityフィールドを埋めます。しかし、EntityManagerをエンティティに挿入することを意味します(または同様のものと悪いもの...)
  2. 新しい数値フィールドsubEntityIdを追加して、上記のような特別なセッターでデータを取得します。コントローラを使用して読み取った後、SubEntityオブジェクトをデータベースから取得し、メソッドの後にデシリアライズして使用します。あまりにも私によく見えません...

何か提案がありますか?私は、Stackoverflowのいくつかの同様の質問がありますが、誰も私の特別なケースを説明していないと私には思われる。

事前に感謝します。

答えて

1

実際にあなたがドン余分なフィールドやセッターを作成する必要はありません。考えられるアプローチは、独自のSerializer handlerを作成し、それをマッピングに使用することです。

私はすでにin this topicに回答していますので、そこでコードサンプルを入手できます。

+0

非常に役に立ちます!ありがとうございました! – ahuemmer

0

ここで私はあなたのコントローラでjms_serializer.initialized_object_constructor

<?php 
namespace MyApp\Bundle\CoreBundle\Serializer; 
use JMS\Serializer\VisitorInterface; 
use JMS\Serializer\Metadata\ClassMetadata; 
use JMS\Serializer\DeserializationContext; 
use JMS\Serializer\Construction\ObjectConstructorInterface; 
class InitializedObjectConstructor implements ObjectConstructorInterface 
{ 
    private $fallbackConstructor; 
    public function __construct(ObjectConstructorInterface $fallbackConstructor) 
    { 
     $this->fallbackConstructor = $fallbackConstructor; 
    } 
    public function construct(VisitorInterface $visitor, ClassMetadata $metadata, $data, array $type, DeserializationContext $context) 
    { 
     if ($context->attributes->containsKey('target') && $context->getDepth() === 1) { 
      return $context->attributes->get('target')->get(); 
     } 
     return $this->fallbackConstructor->construct($visitor, $metadata, $data, $type, $context); 
    } 
} 

ためにこのクラスを追加YAML

jms_serializer.object_constructor: 
    alias: jms_serializer.initialized_object_constructor 
    public: false 

jms_serializer.initialized_object_constructor: 
    class: MyApp\Bundle\CoreBundle\Serializer\InitializedObjectConstructor 
    arguments: ["@jms_serializer.unserialize_object_constructor"] 

でそれを書き、あなたのサービス設定にこれを追加します。

protected function flushRequestData(Request $request, $entity = null) 
{ 
    $data = $request->getContent(); 
    $dm = $this->get('doctrine_mongodb.odm.default_document_manager'); 
    $context = new DeserializationContext(); 
    if ($entity) { 
     $context->attributes->set('target', $entity); 
    } 

    $deserializedObj = $this->get('serializer')->deserialize(
     $data, 
     $this->getRepository()->getClassName(), 
     'json', 
     $context 
    ); 

    // After deserialized into your entity you need to manually set each of the related entity one by one manually 
} 
関連する問題