我已经使用Symfony序列化程序来序列化我的Recherche
对象。
在Recherche
对象中,我有子对象:Categorie
和Lieu
。
当我反序列化我的Recherche
对象时,所有子对象都在数组中转换。我希望他们再次成为对象。
这就是我序列化对象的方式:
$encoders = array(new JsonEncoder());
$normalizer = new ObjectNormalizer();
$normalizer->setIgnoredAttributes(array('parent', 'enfants'));
$normalizer->setCircularReferenceHandler(function ($object) {
return $object->getCode();
});
$normalizers = array($normalizer);
$serializer = new Serializer($normalizers, $encoders);
$rechercheJson= $serializer->serialize($recherche, 'json');
这就是我反序列化的方式:
$encoders = array(new JsonEncoder());
$normalizer = new ObjectNormalizer();
$normalizer->setIgnoredAttributes(array('parent', 'enfants'));
$normalizer->setCircularReferenceHandler(function ($object) {
return $object->getCode();
});
$normalizers = array($normalizer);
$serializer = new Serializer($normalizers, $encoders);
$recherche = $serializer->deserialize($recherche_json, Recherche::class, 'json');
我想也许与规范化程序有关,但我找不到任何可以帮助我完成文档的工作。
任何人都有想法提供帮助吗?
谢谢!
编辑: 看到这篇文章后:Denormalize nested structure in objects with symfony 2 serializer
我试过了:
$encoders = array(new JsonEncoder());
$normalizer = new ObjectNormalizer(null, null, null, new SerializationPropertyTypeExtractor());
$normalizer->setIgnoredAttributes(array('parent', 'enfants'));
$normalizer->setCircularReferenceHandler(function ($object) {
return $object->getCode();
});
$normalizers = array($normalizer, new ArrayDenormalizer());
$serializer = new Serializer($normalizers, $encoders);
$recherche = $serializer->deserialize($recherche_json, Recherche::class, 'json');
SerializationPropertyTypeExtractor:
class SerializationPropertyTypeExtractor implements PropertyTypeExtractorInterface {
/**
* {@inheritdoc}
*/
public function getTypes($class, $property, array $context = array())
{
if (!is_a($class, Recherche::class, true)) {
return null;
}
if ('make' !== $property) {
return null;
}
if ('lieu' === $property)
{
return [new Type(Type::BUILTIN_TYPE_OBJECT, true, LieuRecherche::class)];
}
if ('categorie' === $property)
{
return [new Type(Type::BUILTIN_TYPE_OBJECT, true, Categorie::class)];
}
return null;
}
}
这很好用!
答案 0 :(得分:1)
我遇到了类似的问题,并尝试使用自定义的PropertyTypeExtractor解决该问题。 由于我有很多带有嵌套对象的实体,因此当嵌套对象再次嵌套对象时,这也很麻烦。
我使用PhpDocExtractor和ReflectionExtractor找到了更好的解决方案,它们可以为您提取属性信息。
$encoder = [new JsonEncoder()];
$extractor = new PropertyInfoExtractor([], [new PhpDocExtractor(), new ReflectionExtractor()]);
$normalizer = [new ArrayDenormalizer(), new ObjectNormalizer(null, null, null, $extractor)];
$serializer = new Serializer($normalizer, $encoder);
$result = $serializer->deserialize($data,someEntity::class,'json');
这为我完成了所有工作。我希望这会对某人有所帮助。
答案 1 :(得分:0)
参考:我的评论。 我知道您正在以经典的方式使用序列化器,但我建议您应用推荐的策略模式,这样您就可以完全控制组件并且可以轻松扩展。
所以我的想法是你为标准化和非规范化创建单独的类,如下所示:
<?php
declare(strict_types=1);
namespace App\Denormalizer;
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
use Symfony\Component\Serializer\Exception\CircularReferenceException;
use Symfony\Component\Serializer\Exception\InvalidArgumentException;
use Symfony\Component\Serializer\Exception\LogicException;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
/**
* Class ConfigDenormalizer
* @package App\Denormalizer
*/
class ConfigDenormalizer implements DenormalizerInterface
{
/**
* @param mixed $data
* @param string $class
* @param null $format
* @param array $context
* @return array
*/
public function denormalize($data = [], $class, $format = null, array $context = array())
{
$result = [];
foreach($data as $key => $config) {
$result[ $config['attribute'] ] = $config['valorem'];
}
return $result;
}
/**
* @param mixed $data
* @param string $type
* @param null $format
* @return bool
*/
public function supportsDenormalization($data, $type, $format = null)
{
return $type === self::class;
}
}
<?php
declare(strict_types=1);
namespace App\Normalizer;
use Symfony\Component\Form\Form;
use Symfony\Component\Serializer\Exception\CircularReferenceException;
use Symfony\Component\Serializer\Exception\InvalidArgumentException;
use Symfony\Component\Serializer\Exception\LogicException;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
/**
* Class WidgetConfigNormalizer
* @package App\Normalizer
*/
class WidgetAttributeNormalizer implements NormalizerInterface
{
/**
* @param object $form
* @param null $format
* @param array $context
* @return array
*/
public function normalize($form, $format = null, array $context = array()): array
{
$result = [];
foreach($form->getData() as $key => $value) {
$result[] = [
'attribute' => (string) $key,
'valorem' => (string) $value,
];
}
return $result;
}
/**
* @param mixed $form
* @param null $format
* @return bool
*/
public function supportsNormalization($form, $format = null)
{
if($form instanceof Form) {
return $form->getName() === 'widgetAttribute';
}
}
}
你可以这样称呼它:
//denormalize
$this->denormalizer->denormalize(
json_decode($response->getContent(), true),
ConfigDenormalizer::class
);
//normalize
$form = $this->formFactory->create(myConfigFormType::class);
$form->submit($data);
$this->normalizer->normalize($form);
或者如果你想使用序列化器(注意我们不需要json_decode):
//deserialize
$array = $this->serializer->deserialize(
$response->getContent(),
ConfigDenormalizer::class,
'json'
);
//serialize
$json = $this->serialize->serialize($form, 'json');
当然在你的denormalizer中你可以将你的数组转换成一个普通的旧php对象(实体)。或只输出一个数组,选择权在你手中。
这样你所做的就是将SerializerInterface注入你的控制器:
use Symfony\Component\Serializer\SerializerInterface;
class EmbedController extends Controller
{
/**
* @var SerializerInterface
*/
private $serializer;
public function __construct(SerializerInterface $serializer)
{
$this->serializer = $serializer;
}
}
这种方法使得单元测试也变得更加容易,因为所有东西都是分离的,因此可以进行模拟。 :)
它还值得检查文档: https://symfony.com/doc/current/components/serializer.html
特别是顶部的图像,它是一个很棒的记忆提示,关于你应该使用每个类的方式。
希望这有帮助。