php - programacion - funcion anidada c++
Desnormalizar la estructura anidada en objetos con el serializador Symfony 2 (2)
Estoy trabajando en el proyecto Symfony 2 con la versión 2.8 y estoy usando el componente integrado Serializer -> http://symfony.com/doc/current/components/serializer.html
Tengo una estructura JSON proporcionada por un servicio web. Después de la deserialización, quiero desnormalizar mi contenido en objetos. Aquí está mi estructura (modelo / marca en un contexto de aplicación de automóvil).
[{
"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"
}
}
}]
Mi idea es llenar un objeto VehicleModel
que contiene una referencia a un objeto VehicleMake
.
class VehicleModel {
public $id;
public $code;
public $model;
public $make; // VehicleMake
}
Esto es lo que hago:
// Retrieve data in JSON
$data = ...
$serializer = new Serializer([new ObjectNormalizer(), new ArrayDenormalizer()], [new JsonEncoder()]);
$models = $serializer->deserialize($data, ''/Namespace/VehicleModel[]'', ''json'');
Como resultado, mi objeto VehicleModel
está correctamente rellenado, pero $make
es lógicamente una matriz clave / valor. Aquí quiero un VehicleMake
lugar.
Hay una manera de hacer eso ?
Gracias
ObjectNormalizer
necesita más configuración. Al menos deberá proporcionar el cuarto parámetro de tipo PropertyTypeExtractorInterface
.
Aquí hay un ejemplo (algo hacky):
<?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);
Tenga en cuenta que en su ejemplo json, la primera entrada tiene una matriz como valor para make
. Tomé esto como un error tipográfico, si es deliberado, por favor deje un comentario.
Para que esto sea más automático, es posible que desee experimentar con PhpDocExtractor
.
En los casos en que necesitas más flexibilidad en la desnormalización, es bueno crear tus propios denormalizadores.
$serializer = new Serializer(
[
new ArrayNormalizer(),
new VehicleDenormalizer(),
new VehicleMakeDenormalizer()
], [
new JsonEncoder()
]
);
$models = $serializer->deserialize(
$data,
''/Namespace/VehicleModel[]'',
''json''
);
Aquí el código aproximado de tal denormalizador
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);
...
}
}
Solo tengo dudas sobre si debemos confiar en $this->denormalizer->denormalize
(que funciona correctamente solo porque usamos Symfony/Component/Serializer/Serializer
) o debemos inyectar de forma explícita VehicleMakeDenormalizer
en VehicleDenormalizer
$vehicleDenormalizer = new VehicleDenormalizer();
$vehicleDenormalizer->setVehicleMakeDenormalizer(new VehicleMakeDenormalizer());