如何从 jms 中的数组 id 反序列化?
How deserialize from array ids in jms?
我不知道如何从 ID 数组反序列化对象?这是我的数组的一个简单示例。
"roles":["1","2","3"]
但是在尝试时我得到了对象预期的错误-class AppBundle\Entity\Role...有什么东西吗?谢谢大家的关注!
它正在反序列化您的数组,但它会尝试将其反序列化为 AppBundle\Entity\Role
类型的对象数组,这似乎与您的值 "1"
、"2"
和依此类推,因此会抛出错误,因为它无法实例化对象。
您必须确保您的内容符合预期 class。
如果您可以分享 Class 对 Role
的定义,我们或许可以帮助您了解数组的外观(例如 [["id": 1], ["id": 2], ["id": 3]] 可能)。
问题是LBA在他的回答中提到的问题。基本上为了让 jms 序列化程序创建一个对象,它需要提供一个数组。如果您可以更改 api 的结构,则解决方案也很好。
我假设你的 $role jms 配置看起来像这样
/**
* @var ArrayCollection
*
* @JMS\Expose
* @JMS\Accessor(setter="setRoles")
* @JMS\SerializedName("roles")
* @JMS\Type("ArrayCollection<Role>")
* @JMS\Groups({"...."})
*
*/
private $roles;
在这种情况下,Jms 将期望获得数组数组,就像提到的 LBA 一样。相反,如果您希望他保留当前结构 ("roles":["1","2","3"]) 而不是 "roles":["id": 1], ["id": 2], ["id": 3]],还有一个选择。您可以扩展 JsonDeserializationVisitor,这是您武器库中的一个非常强大的工具,几乎可以用 jms 做任何您想做的事情。
要做到这一点,首先像这样改变你的@Type(你会明白为什么后面)
* @JMS\Type("ArrayCollection<Role,Expand<id>>")
现在你使用参数覆盖,来扩展 JsonDeserializationVisitor,像这样
<parameter key="jms_serializer.json_deserialization_visitor.class">MyBundle\Services\JsonDeserializationVisitor.php</parameter>
然后像这样定义新的访问者。
<?php
namespace MyBundle\Services\JmsSerializer;
use JMS\Serializer\Context;
use JMS\Serializer\JsonDeserializationVisitor as ParentJsonDeserializationVisitor;
use JMS\Serializer\Metadata\ClassMetadata;
use JMS\Serializer\Metadata\PropertyMetadata;
class JsonDeserializationVisitor extends ParentJsonDeserializationVisitor
{
/**
* @param PropertyMetadata $metadata
* @param mixed $data
* @param Context $context
*/
public function visitProperty(PropertyMetadata $metadata, $data, Context $context)
{
//This type is the information you put into the @Type annotation.
$type = $metadata->type;
$expand = null;
.......
/*Here you can extract the Expand<id> part that you added to the @Type config.
The Expand part will help you identify the fact that this property needs to be expanded and the id part will tell you how to expand id.
Based on if you do find this you will probably set a variable like $expand = $key, where $key is the "id" part.*/
......
if ($expand !== null) {
$expandedData = [];
foreach($data as $key->$value)
{
$expandedData[$key]=["$expand":$value];
}
parent::visitProperty($metadata, $expandedData, $context);
} else {
parent::visitProperty($metadata, $data, $context);
}
}
这是基本的东西。随心所欲地重构代码,这只是为了快速证明概念。 Expand 也是我将其命名为示例的方式。你可以用任何你喜欢的名字来使用它。很抱歉没有提供从 $type 中提取它的代码,但我现在不记得 $type 的结构。此外,如果您执行 Expand<'id'> 之类的操作,结构也会发生变化,因此请尝试一下,看看哪个最适合您。基本上,使用这种方法,您可以扩展功能并将其添加到您想要的任何 jms 类型。例如,您可以添加类似
的内容
@JMS\Type("string<translatable>")
然后扩展 JsonSerializationVisitor:visitString 以在返回 $data 之前调用 $translator->trans($data) ,这样你就可以在序列化之前翻译一个字符串。
像这样
<?php
namespace MyBundle\Service\JmsSerializer;
use JMS\Serializer\Context;
use JMS\Serializer\JsonSerializationVisitor as ParentJsonSerializationVisitor;
use Symfony\Component\Translation\Translator;
class JsonSerializationVisitor extends ParentJsonSerializationVisitor
{
/**
* @var Translator;
*/
private $translator;
const TRANSLATABLE = "translatable";
/**
* @param string $data
* @param array $type
* @param Context $context
* @return string
*/
public function visitString($data, array $type, Context $context)
{
$translatable = $this->getParameters(self::TRANSLATABLE, $type['params']);
if ($translatable) {
$data = (string)$this->translator->trans($data);
}
return parent::visitString($data, $type, $context);
}
.....................
希望这对您有所帮助。如果您有任何问题,请告诉我。
亚历山德鲁·科索伊
我不知道如何从 ID 数组反序列化对象?这是我的数组的一个简单示例。
"roles":["1","2","3"]
但是在尝试时我得到了对象预期的错误-class AppBundle\Entity\Role...有什么东西吗?谢谢大家的关注!
它正在反序列化您的数组,但它会尝试将其反序列化为 AppBundle\Entity\Role
类型的对象数组,这似乎与您的值 "1"
、"2"
和依此类推,因此会抛出错误,因为它无法实例化对象。
您必须确保您的内容符合预期 class。
如果您可以分享 Class 对 Role
的定义,我们或许可以帮助您了解数组的外观(例如 [["id": 1], ["id": 2], ["id": 3]] 可能)。
问题是LBA在他的回答中提到的问题。基本上为了让 jms 序列化程序创建一个对象,它需要提供一个数组。如果您可以更改 api 的结构,则解决方案也很好。
我假设你的 $role jms 配置看起来像这样
/**
* @var ArrayCollection
*
* @JMS\Expose
* @JMS\Accessor(setter="setRoles")
* @JMS\SerializedName("roles")
* @JMS\Type("ArrayCollection<Role>")
* @JMS\Groups({"...."})
*
*/
private $roles;
在这种情况下,Jms 将期望获得数组数组,就像提到的 LBA 一样。相反,如果您希望他保留当前结构 ("roles":["1","2","3"]) 而不是 "roles":["id": 1], ["id": 2], ["id": 3]],还有一个选择。您可以扩展 JsonDeserializationVisitor,这是您武器库中的一个非常强大的工具,几乎可以用 jms 做任何您想做的事情。
要做到这一点,首先像这样改变你的@Type(你会明白为什么后面)
* @JMS\Type("ArrayCollection<Role,Expand<id>>")
现在你使用参数覆盖,来扩展 JsonDeserializationVisitor,像这样
<parameter key="jms_serializer.json_deserialization_visitor.class">MyBundle\Services\JsonDeserializationVisitor.php</parameter>
然后像这样定义新的访问者。
<?php
namespace MyBundle\Services\JmsSerializer;
use JMS\Serializer\Context;
use JMS\Serializer\JsonDeserializationVisitor as ParentJsonDeserializationVisitor;
use JMS\Serializer\Metadata\ClassMetadata;
use JMS\Serializer\Metadata\PropertyMetadata;
class JsonDeserializationVisitor extends ParentJsonDeserializationVisitor
{
/**
* @param PropertyMetadata $metadata
* @param mixed $data
* @param Context $context
*/
public function visitProperty(PropertyMetadata $metadata, $data, Context $context)
{
//This type is the information you put into the @Type annotation.
$type = $metadata->type;
$expand = null;
.......
/*Here you can extract the Expand<id> part that you added to the @Type config.
The Expand part will help you identify the fact that this property needs to be expanded and the id part will tell you how to expand id.
Based on if you do find this you will probably set a variable like $expand = $key, where $key is the "id" part.*/
......
if ($expand !== null) {
$expandedData = [];
foreach($data as $key->$value)
{
$expandedData[$key]=["$expand":$value];
}
parent::visitProperty($metadata, $expandedData, $context);
} else {
parent::visitProperty($metadata, $data, $context);
}
}
这是基本的东西。随心所欲地重构代码,这只是为了快速证明概念。 Expand 也是我将其命名为示例的方式。你可以用任何你喜欢的名字来使用它。很抱歉没有提供从 $type 中提取它的代码,但我现在不记得 $type 的结构。此外,如果您执行 Expand<'id'> 之类的操作,结构也会发生变化,因此请尝试一下,看看哪个最适合您。基本上,使用这种方法,您可以扩展功能并将其添加到您想要的任何 jms 类型。例如,您可以添加类似
的内容 @JMS\Type("string<translatable>")
然后扩展 JsonSerializationVisitor:visitString 以在返回 $data 之前调用 $translator->trans($data) ,这样你就可以在序列化之前翻译一个字符串。
像这样
<?php
namespace MyBundle\Service\JmsSerializer;
use JMS\Serializer\Context;
use JMS\Serializer\JsonSerializationVisitor as ParentJsonSerializationVisitor;
use Symfony\Component\Translation\Translator;
class JsonSerializationVisitor extends ParentJsonSerializationVisitor
{
/**
* @var Translator;
*/
private $translator;
const TRANSLATABLE = "translatable";
/**
* @param string $data
* @param array $type
* @param Context $context
* @return string
*/
public function visitString($data, array $type, Context $context)
{
$translatable = $this->getParameters(self::TRANSLATABLE, $type['params']);
if ($translatable) {
$data = (string)$this->translator->trans($data);
}
return parent::visitString($data, $type, $context);
}
.....................
希望这对您有所帮助。如果您有任何问题,请告诉我。
亚历山德鲁·科索伊