2016-04-15 6 views
3

Doctrineオブジェクトグラフをシリアライズおよびデシリアライズしようとしています。JMSシリアライザを使用して再帰オブジェクトを処理する方法

構造はかなり複雑ですが、この例は、私の問題を要約:

EmployeeにOneToMany関係にCompanyエンティティがあります。
Employeeエンティティには、CompanyのManyToOne関係があります。次のように

これが連載されています

{ 
    "company": { 
     "name": "MegaCorp", 
     "employees": [{ 
      "name": "John Doe", 
      "company": null 
     }] 
    } 
} 

だから nullEmployeeの親 Companyへの参照。シリアル化の場合はこれでいいです。 しかし、このjsonを逆シリアル化すると、 Employeeオブジェクトの null Companyが得られます。私が望むのは、親への正しい参照を得ることです(そして期待する)。 Company

これはJMSシリアライザを使用して可能ですか?もしそうなら、どうすればできますか?
できない場合は、どのような回避策をとることができますか?それは大きなグラフであることを覚えています。私はそれを手動で実行したくありません。

+1

参照をnullにする代わりに、そのIDを使用します。基本的には、実際のオブジェクトの代わりにプロキシが必要です。 JMSがこれをサポートしているかどうかはわかりません。 – Gordon

+0

これは可能な解決策ですが、実際には疑問があります。JMSはそれをサポートしていますか? –

+0

私は '@ preSerialize'と' @ postSerialize'フックを持っていることを知っています。だから、それは実行可能です。 – Gordon

答えて

2

デシリアライズ時に、シリアライザがオブジェクトが同一であるか実際に同じオブジェクトであるかを知る方法はありません。あなたがそれらを再帰的に入れ子にすることができたとしても。

ただし、@Accessor注釈をビジネスロジックと組み合わせると、望ましい結果が得られます。だからあなたの例のオフに行く:

class Company { 
    /** 
    * @Accessor(setter="addEmployees") 
    */ 
    private $employees; 

    public function addEmployee(Employee $employee) 
    { 
     if (!$this->employees->contains($employee)) { 
      $this->employees[] = $employee; 
      $employee->setCompany($this); 
     } 
    } 

    public function addEmployees($employees) 
    { 
     foreach ($employees as $employee) { 
      $this->addEmployee($employee); 
     } 
    } 
} 

class Employee { 
    /** 
    * @Accessor(setter="setCompany") 
    */ 
    private $company; 

    public setCompany(Company $company = null) 
    { 
     $this->company = $company; 

     if ($company) { 
      $company->addEmployee($this); 
     } 
    } 
} 

私はあなたがおそらく既にあなたのコードでこれらのメソッドのいくつかを持っているとして、これは@PostDeserializeを使用するよりも、より自然なアプローチだと思います。また、それは両方の方法で契約を保証するので、あなたがEmployeeから始めるのであれば、同じ結果が得られます。

+0

これは実際に会社にPostDeserializeフックを含む私の現在のソリューションよりも若干良好な実装です。基本的な考え方も同じです。 –

+0

うん。私はそれを歩き回るはありません...私が言ったように、シリアライザは自体にJSON構造によって強制されるものから離れて任意の関係をピックアップするための方法はありません怖いです。 –

+0

あなたは正しいと思います。 @Accessorメソッドを使用して実装しました。魅力的に機能します。ありがとう! –

0

オブジェクトを逆シリアル化したときにリファレンスを手動で設定するのはどうですか?このようなもの:

class Company { 

    .... 

    @PostDeserialize 
    public function setReferences() 
    { 
     foreach($this->employees as $employee){ 
      $employee->setCompany($this); 
     } 
    } 
} 
0

JSONエンティティをできるだけシンプルにすることをお勧めします。この種の問題に対処する必要がある場合は、データモデルを再考する必要があります。

さらに、HATEOAS(アプリケーション状態のエンジンとしてのHypermedia)の使用は、APIを通じてより良いナビゲーションを作成するためにハイパーテキストリンクを使用する必要があるという原則です。次のようになります。

{ 
    "id": 711, 
    "manufacturer": "bmw", 
    "model": "X5", 
    "seats": 5, 
    "drivers": [ 
    { 
    "id": "23", 
    "name": "Stefan Jauker", 
    "links": [ 
    { 
    "rel": "self", 
    "href": "/api/v1/drivers/23" 
    } 
    ] 
    } 
] 
} 
+0

残念ながら、それは私がとのインターフェースに持っていたレガシーアプリケーションです。そうでなければ、私はもっと同意できませんでした! –

+0

これで分かりました。だから、このJSONを読むクライアントは、この循環的な依存関係を認識し、JSONをデコードする際の参照を設定する必要があります。 – Rafa0809

関連する問題