Symfony 3.4文档说明了反序列化数组的以下内容:
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Normalizer\ArrayDenormalizer;
use Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer;
use Symfony\Component\Serializer\Serializer;
$serializer = new Serializer(
array(new GetSetMethodNormalizer(), new ArrayDenormalizer()),
array(new JsonEncoder())
);
$data = ...; // The serialized data from the previous example
$persons = $serializer->deserialize($data, 'Acme\Person[]', 'json');
json字符串如下:
[{ “名称”: “foo” 的, “年龄”:99, “运动员”:假},{ “名称”: “棒”, “年龄”:33, “运动员”:真}]
所以我尝试用我的XML结构做同样的事情。这不是一个真实的结构,因为我正在测试这个东西。
XML结构:
<<<EOF
<response>
<book>
<titulo>foo</titulo>
<isbn>99</isbn>
<autor>Autor</autor>
<editor>Editor</editor>
</book>
<book>
<titulo>foo2</titulo>
<isbn>100</isbn>
<autor>Autor2</autor>
<editor>Editor2</editor>
</book>
</response>
EOF;
Response是默认的根节点名称。我有一个Book实体,其字段定义相同。我尝试反序列化:
use AppBundle\Entity\Book;
use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Serializer\Encoder\XmlEncoder;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\PropertyAccess\PropertyAccess;
use Symfony\Component\Serializer\Normalizer\ArrayDenormalizer;
use Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer;
$encoders = array(new XmlEncoder(), new JsonEncoder());
$normalizers = array(new GetSetMethodNormalizer(), new ArrayDenormalizer());
$serializer = new Serializer($normalizers, $encoders);
$serializer->deserialize($data, 'AppBundle\Entity\Book[]', 'xml');
当我执行deserialize变量的var_dump时,输出如下:
array(1){[“book”] => object(AppBundle \ Entity \ Book)#385(11){[“isbn”:protected] => NULL [“autor”:protected] => NULL [“titulo” :protected] => NULL [“fecha_ini”:protected] => NULL [“fecha_fin”:protected] => NULL [“editor”:protected] => NULL [“imgUrl”:protected] => NULL [“cod_autor” :protected] => NULL [“cod_editorial”:protected] => NULL [“cod_coleccion”:protected] => NULL [“cod_mat”:protected] => NULL}}
当我期望2个元素时,数据不被识别,并且数组只有一个元素。
有人经历过这样的事吗?你能帮我在哪里寻找解决方案吗?
提前致谢。
XML不是JSON,根元素不是“只是数组的包装器”,所以你必须付出适当的尊重。有两种方法可以解决这个问题:
1.为根元素引入反序列化模型 - 类似于
class Response
{
/**
* @var Book[]
*/
protected $book;
/**
* @return Book[]
*/
public function getBook(): array
{
return $this->book;
}
/**
* @param Book[] $book
*/
public function setBook(array $book): void
{
$this->book = $book;
}
}
然后访问像这样的书
$response = $serializer->deserialize($xml, 'App\Entity\Response', 'xml');
$books = $response->getBook();
但是,在这种情况下,您的简单序列化程序配置是不够的 - 为了将书籍正确地反序列化为Book
实例,有必要为extract type information for the nested entities添加额外的功能:
$encoders = array(new XmlEncoder());
$normalizers = array(new GetSetMethodNormalizer(null, null, new PhpDocExtractor()), new ArrayDenormalizer()); // <- PhpDocExtractor
$serializer = new Serializer($normalizers, $encoders);
PhpDocExtractor
从PhpDoc评论中提取类型信息。
2.引入自定义非规范化器
或者,您可以使用自定义的非规范化器直接挂钩到反序列化过程
use App\Entity\Book;
use Symfony\Component\Serializer\Normalizer\ArrayDenormalizer;
class BookArrayDenormalizer extends ArrayDenormalizer
{
public function supportsDenormalization($data, $type, $format = null, array $context = [])
{
// only support deserialization of Book[]
return Book::class.'[]' === $type;
}
public function denormalize($data, $class, $format = null, array $context = [])
{
return parent::denormalize(
$data['book'], // this is the magic to ignore the root element
$class, $format, $context
);
}
}
并且喜欢在没有包装对象的情况下反序列化一系列Books:
$normalizers = array(new GetSetMethodNormalizer(), new BookArrayDenormalizer(), new ArrayDenormalizer()); // add the new denormalizer
$encoders = array(new XmlEncoder());
$serializer = new Serializer($normalizers, $encoders);
$books = $serializer->deserialize($xml, 'App\Entity\Book[]', 'xml');