2012-10-05 14 views
8

グループを使用して多数のリレーションを持つエンティティをシリアル化する際に問題があります。 このように、関連するエンティティのシリアル化に問題があります。リレーションを持つエンティティのJMSSerializerBundleシリアル化グループ

私は2つのエンティティを持っているとしましょう:製品と関連要素。

/** 
* 
* @Serializer\ExclusionPolicy("none") 
*/ 
class Product { 

    /** 
    * Primary key 
    * @var integer $id 
    * 
    * @ORM\Column(name="id", type="integer") 
    * @ORM\Id 
    * @ORM\GeneratedValue(strategy="AUTO") 
    * 
    * @Serializer\Groups({"list","details"}) 
    * @Serializer\Type("integer") 
    */ 
    protected $id; 

    /** 
    * @Serializer\Groups({"list","details"}) 
    * @Serializer\Type("string") 
    */ 
    protected $name; 

    /** 
    * @ORM\Column(name="description", type="string", length=4096, nullable=true) 
    * 
    * @Serializer\Groups({"details"}) 
    * @Serializer\Type("string") 
    */ 
    protected $description; 

    /** 
    * @var ArrayCollection 
    * 
    * @ORM\OneToMany(targetEntity="Madden\ProjectBundle\Entity\ProjectResource", mappedBy="project") 
    * @Serializer\Groups({"details"}) 
    * @Serializer\Type("ArrayCollection<Element>") 
    */ 
    protected $details1; 

    /** 
    * Relation to project tasks 
    * @ORM\OneToMany(targetEntity="Madden\ProjectBundle\Entity\ProjectTask", mappedBy="project") 
    * @Serializer\Exclude() 
    * @Serializer\Type("ArrayCollection<Element>") 
    */ 
    protected $details2; 

    ... 

} 

要素実体は、同様の構造を有する:

/** 
* 
* @Serializer\ExclusionPolicy("none") 
*/ 
class Element { 

    /** 
    * Primary key 
    * @var integer $id 
    * 
    * @ORM\Column(name="id", type="integer") 
    * @ORM\Id 
    * @ORM\GeneratedValue(strategy="AUTO") 
    * 
    * @Serializer\Groups({"list","details"}) 
    * @Serializer\Type("integer") 
    */ 
    protected $id; 

    /** 
    * @Serializer\Groups({"list","details"}) 
    * @Serializer\Type("string") 
    */ 
    protected $name; 

    /** 
    * @ORM\Column(name="description", type="string", length=4096, nullable=true) 
    * 
    * @Serializer\Groups({"details"}) 
    * @Serializer\Type("string") 
    */ 
    protected $description; 

    ... 
} 

私の問題は、私は「詳細」グループのエンティティで製品をシリアライズだとき、私は元素の唯一のIDをシリアライズしたいということですが、あなたはエンティティを見るようにすべてのエンティティに統一されたグループを持ち、 'product_details'、 'element_details'などの何百ものグループを作成しないようにするため、Productと同じグループを定義しました(要素オブジェクトの詳細が必要な場合)。

私はリレーションやそのようなものを訪問するときにシリアル化グループを最終的に変更する方法はありますか?ハンドラーは多分かそのようなものですか?

+2

...より柔軟な、より少ない冗長、保守が容易、かつ:@aferberによって提案された解決策は、多くの点で優れているようだ言われていること

それはあなたが常に直列化されているものを完全に制御できるので、かなり素晴らしかったです。欠点は、明らかに、複数のクラスを直列化するときにコードがどれほど冗長であるかです。私は 'xxx_list' /' xxx_details'の代わりに 'xxx_partial' /' xxx_full'も使用します。 – AdrienBrault

+1

@AdrienBrault返信ありがとうございます。はい、私はそのソリューションを今使っていますが、それは欠点があります。つまり、多くのエンティティが共通のエンティティ辞書を持っている場合、グループをすべての関連エンティティで定義する必要があります。エンティティグループのアノテーションは巨大になります – mrMantir

+1

[VirtualProperty] /jmsyst.com/libs/serializer/master/reference/annotations#virtualproperty)? –

答えて

7

残念ながら任意の助け

よろしくと感謝、あなたが本当に(しかし;-)読み続ける)ことができない、うまく少なくともないシリアライザライブラリへの変更なし。原因は、グループのリストが、GroupExclusionStrategyContextによって参照される)内に固定されていることです。実際には、コード内にアサーションがあり、一度(デ)シリアライゼーションが実行されると除外ストラテジーの変更を防ぐことができます。

しかし、私のプロジェクトでもまったく同じ問題がありました。シリアライザコードに必要な変更が加えられました。コードを少しきれいにしてGithub(https://github.com/andreasferber/serializer/tree/recursion-groups)にアップロードしました。

サブオブジェクトに降順で追加、削除、または上書きできる新しいプロパティメタデータを追加します。注釈で、それは次のようになります。

/** 
* @Serializer\RecursionGroups(set={"foo", "bar"}, add={"baz"}, remove={"Default"}) 
*/ 
private $myProperty; 

あなたにもXMLやYAMLのメタデータを使用することができるはず、私はそれらを使用していないと私はまだテストケースを追加していないことから、しかし、これはテストされていません。リファレンスドキュメントを見てください。私はまだどちらの最適化も行っていないので、あなたのエンティティが本当に大きくて深く入れ子になっていると、パフォーマンスに著しい影響を与えるかもしれません。

私が必要としているだけでなく、いくつかのテストを追加してアップストリームに提出しようとすると、これが役に立つかどうか、またはご意見があれば教えてください。

+0

一見して本当に良いように見えます。今日または明日に試してみます –

+0

正式なシリアライザは、この一般的な問題のための最良の "一般的な"解決策であるが、まだ十分な解決策が見つかっていない。VirtualPropertyソリューションを利用する。 –

+2

上流へのプルリクエストを考慮する必要がある。 – Szpadel

0

この解決策は、実際にofficial documentationに記載されています。私は `product_detail` /` product_list`などのソリューションを使用しました

+0

公式文書の解決策がうまくいかないという愚かな理由がある –