2017-08-24 5 views
1

J'en ai un Agrégat racine - Produit - qui a peu de champs et certains d'entre eux sont des objets, comme le prix. Il ressemble à ça (bien sûr, il est simplifié):Sérialisation des champs privés d'objets imbriqués

Product 
{ 
    private $price; 

    public function __construct(Price $price) 
    { 
     $this->price = $price; 
    } 
} 


Price 
{ 

    private $currency; 
    private $amount; 

    public function __construct($currency, $amount) 
    { 
     $this->currency = $currency; 
     $this->amount= $amount; 
    } 
} 

Cette racine globale ne contient pas de méthode « getPrice », ce n'est pas nécessaire dans le domaine.

La question: J'ai besoin de sérialisation cet agrégat, mais je voudrais avoir dans ce format:

Product.json

{  
    "priceCurrency": "GBP", 
    "priceAmount": 100 
} 

J'ai essayé avec JMSSerializer, mais peut Je ne comprends vraiment pas de config. Ce par exemple ne fonctionne pas:

Product.yml

Namespace\Product: 
    virtual_properties: 
    getAmount: 
     exp: object.price.amount 
     serialized_name: priceAmount 
     type: integer 
    getCurrency: 
     exp: object.price.currency 
     serialized_name: priceCurrency 
     type: string 

Je comprends que cela est dû au fait, cette partie « exp » est utilisé par Symfony Expression Langue et de ce que Je sais qu'il ne prend pas en charge l'obtention de valeurs à partir de champs privés d'une autre manière que par le biais de leurs méthodes. Je sais aussi que JMSSerializer lui-même supporte cela. Je n'ai pas besoin d'avoir le champ "getPrice" pour sérialiser le champ "price".

Question: Existe-t-il un moyen de réaliser ce que je veux juste par config ou dois-je écrire des écouteurs sur l'événement post_serialize?

+0

Pourquoi utilisez-vous une propriété virtuelle et non seulement la mise en 'serialized_name' sur la propriété elle-même? –

+0

hmm? Comment cela m'aiderait? serialized_name est juste le nom du champ sérialisé, et j'ai du mal à obtenir de la valeur, pas à définir le nom. – mmmm

+0

Peut-être que je ne comprenais pas le problème ... Je pensais que JMS utilisait juste la réflexion pour obtenir des valeurs de champs privés. Est-ce que c'est ce que vous avez des problèmes? Ou est-ce le fait que vous essayez d'obtenir une valeur particulière d'un objet associé? –

Répondre

1

Utilisez quelque chose comme ceci:

<?php 

class Property 
{ 
    protected $reflection; 
    protected $obj; 

    public function __construct($obj) 
    { 
     $this->obj = $obj; 
     $this->reflection = new ReflectionObject($obj); 
    } 

    public function set($name, $value) 
    { 
     $this->getProperty($name)->setValue($this->obj, $value); 
    } 

    public function get($name) 
    { 
     return $this->getProperty($name)->getValue($this->obj); 
    } 

    protected function getProperty($name) 
    { 
     $property = $this->reflection->getProperty($name); 
     $property->setAccessible(true); 
     return $property; 
    } 
} 

// example 
class Foo 
{ 
    protected $bar = 123; 

    public function getBar() 
    { 
     return $this->bar; 
    } 
} 

$foo = new Foo(); 
echo 'original: '.$foo->getBar().PHP_EOL; 

$prop = new Property($foo); 
echo 'reflection - before changes: '.$prop->get('bar').PHP_EOL; 

$prop->set('bar', 'abc'); 

echo 'after changes: '.$foo->getBar().PHP_EOL;