我在使用组序列化具有许多关系的实体时遇到问题。我在以这种方式序列化相关实体时遇到了问题。
假设我有两个实体:产品和相关元素。
/**
*
* @SerializerExclusionPolicy("none")
*/
class Product {
/**
* Primary key
* @var integer $id
*
* @ORMColumn(name="id", type="integer")
* @ORMId
* @ORMGeneratedValue(strategy="AUTO")
*
* @SerializerGroups({"list","details"})
* @SerializerType("integer")
*/
protected $id;
/**
* @SerializerGroups({"list","details"})
* @SerializerType("string")
*/
protected $name;
/**
* @ORMColumn(name="description", type="string", length=4096, nullable=true)
*
* @SerializerGroups({"details"})
* @SerializerType("string")
*/
protected $description;
/**
* @var ArrayCollection
*
* @ORMOneToMany(targetEntity="MaddenProjectBundleEntityProjectResource", mappedBy="project")
* @SerializerGroups({"details"})
* @SerializerType("ArrayCollection<Element>")
*/
protected $details1;
/**
* Relation to project tasks
* @ORMOneToMany(targetEntity="MaddenProjectBundleEntityProjectTask", mappedBy="project")
* @SerializerExclude()
* @SerializerType("ArrayCollection<Element>")
*/
protected $details2;
...
}
元素实体具有类似的结构:
/**
*
* @SerializerExclusionPolicy("none")
*/
class Element {
/**
* Primary key
* @var integer $id
*
* @ORMColumn(name="id", type="integer")
* @ORMId
* @ORMGeneratedValue(strategy="AUTO")
*
* @SerializerGroups({"list","details"})
* @SerializerType("integer")
*/
protected $id;
/**
* @SerializerGroups({"list","details"})
* @SerializerType("string")
*/
protected $name;
/**
* @ORMColumn(name="description", type="string", length=4096, nullable=true)
*
* @SerializerGroups({"details"})
* @SerializerType("string")
*/
protected $description;
...
}
我的问题是,当我用"details"组实体序列化Product时,我只想序列化元素的id,但正如你所看到的,实体已经定义了与Product相同的组(以防我需要元素对象的详细信息),因为我希望在所有实体上都有统一的组,并防止生成数百个组,如"Product_details"、"element_details"等。
当我访问关系或类似的东西时,有没有一种方法可以最终更改序列化组?也许是汉德勒之类的?
问候并感谢的任何帮助
不幸的是,如果不更改序列化程序库,就不能真正(但继续阅读;-))。罪魁祸首是在开始序列化过程的那一刻,组列表就固定在GroupExclusionStrategy
(由Context
引用)中。实际上,代码中有一个断言,可以在(反)序列化运行后防止修改排除策略。
但碰巧的是,我在自己的一个项目中也遇到了完全相同的问题,我在序列化程序代码中进行了必要的更改。我已经清理了一些代码,并将其上传到Github(https://github.com/andreasferber/serializer/tree/recursion-groups)。
它添加了新的特性元数据,在下降到子对象时,可以使用这些元数据添加、删除或覆盖组。有了注释,它看起来像这样:
/**
* @SerializerRecursionGroups(set={"foo", "bar"}, add={"baz"}, remove={"Default"})
*/
private $myProperty;
您应该也能够使用XML或Yaml元数据,但是这是未经测试的,因为我没有使用它们,而且我还没有添加测试用例。请查看参考文档。由于我还没有做任何优化,如果您的实体真的很大并且嵌套很深,那么它可能会对性能产生显著影响。
如果你觉得这很有用,或者你有什么建议,请告诉我,因为如果这不仅仅是我需要的,我会添加一些测试,并尝试向上游提交。
官方文档中实际描述了这方面的解决方案。
话虽如此,@aferber提出的解决方案在许多方面似乎更好:更易于维护,不那么冗长,更灵活。。。
您需要使用setGroups
。
不需要官方文件中使用的_group
后缀
$context->setGroups([
'Default', //if you want
// use this linked entity but show only its id
'group_of_linked_field',
'group_of_linked_field' => [
'id' // you will need to define this group first
],
// use this linked entity and show fields as described
'group_of_other_linked_field',
'group_of_other_linked_field' => [
// just as an example
'Default',
'details',
],
]);
这与addGroup
或addGroups
不兼容!它们都不接受关联数组。setGroups
是您(唯一?)的解决方案。