私はバージョン2.8のSymfony 2プロジェクトに取り組んでおり、組み込みコンポーネントSerializer-> http://symfony.com/doc/current/components/serializer.html を使用しています。
Webサービスによって提供されるJSON構造があります。逆シリアル化後、オブジェクトのコンテンツを非正規化したいと思います。これが私の構造です(車のアプリケーションコンテキストでモデル/製造)。
[{
"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
ObjectNormalizer
にはさらに設定が必要です。少なくとも、タイプPropertyTypeExtractorInterface
の4番目のパラメーターを指定する必要があります。
これは(むしろハッキーな)例です:
<?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);
Jsonの例では、最初のエントリにmake
の値として配列があることに注意してください。これをタイプミスと見なしましたが、意図的なものである場合はコメントを残してください。
これをより自動化するにはPhpDocExtractor
を試してみるとよいでしょう。
非正規化により多くの柔軟性が必要な場合は、独自の非正規化子を作成することをお勧めします。
$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);
...
}
}
$this->denormalizer->denormalize
(Symfony\Component\Serializer\Serializer
を使用しているからといって正しく機能する)に依存しているか、VehicleMakeDenormalizer
をVehicleDenormalizer
に明示的に注入する必要があるのか、疑問に思うだけです。
$vehicleDenormalizer = new VehicleDenormalizer();
$vehicleDenormalizer->setVehicleMakeDenormalizer(new VehicleMakeDenormalizer());