2016-10-14 14 views
9

を持つオブジェクトにネストされた構造を非正規化サービス。 デシリアライズ後、オブジェクト内のコンテンツを非正規化したい。ここに私の構造があります(車のアプリケーションコンテキストでのモデル/メイク)。は、私は、バージョン2.8でのSymfony 2プロジェクトに取り組んでいると私は、ビルドインコンポーネントシリアライザを使用していsymfonyの2シリアライザ

[{ 
"0": { 
    "id": 0, 
    "code": 1, 
    "model": "modelA", 
    "make": { 
     "id": 0, 
     "code": 1, 
     "name": "makeA" 
    } 
    } 
} , { 
"1": { 
    "id": 1, 
    "code": 2, 
    "model": "modelB", 
    "make": { 
     "id": 0, 
     "code": 1, 
     "name": "makeA" 
    } 
    } 
}] 

私の考えはVehicleModelオブジェクトウィッヒがVehicleMakeオブジェクトへの参照が含まれてい移入することです。ここで

class VehicleModel { 
    public $id; 
    public $code; 
    public $model; 
    public $make; // VehicleMake 
} 

は、私が何をすべきかです:結果で

// Retrieve data in JSON 
$data = ... 
$serializer = new Serializer([new ObjectNormalizer(), new ArrayDenormalizer()], [new JsonEncoder()]); 
$models = $serializer->deserialize($data, '\Namespace\VehicleModel[]', 'json'); 

、私のオブジェクトVehicleModelが正しく読み込まれているが、$makeは、論理的には、キー/値の配列です。ここで私は代わりにVehicleMakeが欲しいです。

これを行う方法はありますか?

Thxを

答えて

5

ObjectNormalizerは、複数の設定が必要です。少なくともPropertyTypeExtractorInterfaceの4番目のパラメータを指定する必要があります。あなたの例のJSONでは、最初のエントリはmakeの値として配列を持っていることを

<?php 
use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface; 
use Symfony\Component\PropertyInfo\Type; 
use Symfony\Component\Serializer\Encoder\JsonEncoder; 
use Symfony\Component\Serializer\Normalizer\ArrayDenormalizer; 
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer; 
use Symfony\Component\Serializer\Serializer; 

$a = new VehicleModel(); 
$a->id = 0; 
$a->code = 1; 
$a->model = 'modalA'; 
$a->make = new VehicleMake(); 
$a->make->id = 0; 
$a->make->code = 1; 
$a->make->name = 'makeA'; 

$b = new VehicleModel(); 
$b->id = 1; 
$b->code = 2; 
$b->model = 'modelB'; 
$b->make = new VehicleMake(); 
$b->make->id = 0; 
$b->make->code = 1; 
$b->make->name = 'makeA'; 

$data = [$a, $b]; 

$serializer = new Serializer(
    [new ObjectNormalizer(null, null, null, new class implements PropertyTypeExtractorInterface { 
     /** 
     * {@inheritdoc} 
     */ 
     public function getTypes($class, $property, array $context = array()) 
     { 
      if (!is_a($class, VehicleModel::class, true)) { 
       return null; 
      } 

      if ('make' !== $property) { 
       return null; 
      } 

      return [ 
       new Type(Type::BUILTIN_TYPE_OBJECT, true, VehicleMake::class) 
      ]; 
     } 
    }), new ArrayDenormalizer()], 
    [new JsonEncoder()] 
); 

$json = $serializer->serialize($data, 'json'); 
print_r($json); 

$models = $serializer->deserialize($json, VehicleModel::class . '[]', 'json'); 
print_r($models); 

注:ここでは

は(むしろハック)の例です。私はこれを誤植にしようとしました。それが故意であれば、コメントを残してください。

これをより自動化するにはPhpDocExtractorを試してみるとよいでしょう。

+0

私のjsonにはタイプミスがあります。私は私の質問を更新しました。 –

+0

ObjectNormaliserはコンストラクタで3つの引数のみを必要とし、3つ目はPropertyAccessorInterfaceを実装します。 –

+0

ああ、私はsf3でのみこれをテストしました。だから、APIの変更があった可能性があります。 v2.8でタイプ抽出機能を追加する方法がない場合、この回答はあなたには適していない可能性があります。 – Yoshi

3

非正規化の柔軟性が必要な場合は、独自の非正規化を作成することをお勧めします。

ここ
$serializer = new Serializer(
    [ 
    new ArrayNormalizer(), 
    new VehicleDenormalizer(), 
    new VehicleMakeDenormalizer() 
    ], [ 
    new JsonEncoder() 
    ] 
); 
$models = $serializer->deserialize(
    $data, 
    '\Namespace\VehicleModel[]', 
    'json' 
); 

class VehicleDenormalizer implements DenormalizerInterface, DenormalizerAwareInterface 
    { 
     public function denormalize($data, $class, $format, $context) 
     { 
     $vehicle = new VehicleModel(); 
     ... 
     $vehicleMake = $this->denormalizer->denormalize(
      $data->make, 
      VehicleMake::class, 
      $format, 
      $context 
     ); 
     $vehicle->setMake($vehicleMake); 
     ... 
     } 
    } 

denormalizerなどのラフなコード私は、我々が$this->denormalizer->denormalizeに依存している必要があります上の疑問を持っている(私たちはSymfony\Component\Serializer\Serializerを使用するという理由だけで正常に動作している)か、我々は明示的にVehicleDenormalizer

VehicleMakeDenormalizerを注入しなければなりません
$vehicleDenormalizer = new VehicleDenormalizer(); 
$vehicleDenormalizer->setVehicleMakeDenormalizer(new VehicleMakeDenormalizer()); 
関連する問題