如何使用JMS Serializer处理递归对象

时间:2016-04-15 07:21:49

标签: php jmsserializerbundle jms-serializer

我正在尝试序列化和反序列化Doctrine对象图。

结构非常复杂,但这个例子总结了我的问题:

Company实体与Employee之间存在OneToMany关系 Employee实体与Company具有ManyToOne关系。

这是序列化如下:

{
    "company": {
        "name": "MegaCorp",
        "employees": [{
            "name": "John Doe",
            "company": null
        }]
    }
}

因此null是对Employee的父Company的引用。对于序列化,这没关系。 但是现在当我反序列化这个json时,我在null对象中得到Company Employee。我想要(并且期望)的是获得对父Company的正确引用。

这是否可以使用JMS序列化器,如果可以,怎么办呢? 如果不可能,那么什么是一个好的解决方法?请记住,它是一个大图,我不想手动完成。

3 个答案:

答案 0 :(得分:2)

不幸的是,在反序列化时,序列化程序无法知道对象是相同的还是实际上是同一个对象。即使你可以递归地嵌套它们。

但是,在将@Accessor注释与某些业务逻辑相结合时,您可以获得所需的结果。所以离开你的榜样:

class Company {
    /**
     * @Accessor(setter="addEmployees")
     */
    private $employees;

    public function addEmployee(Employee $employee)
    {
        if (!$this->employees->contains($employee)) {
            $this->employees[] = $employee;
            $employee->setCompany($this);
        }
    }

    public function addEmployees($employees)
    {
        foreach ($employees as $employee) {
            $this->addEmployee($employee);
        }
    }
}

class Employee {
    /**
     * @Accessor(setter="setCompany")
     */
    private $company;

    public setCompany(Company $company = null)
    {
        $this->company = $company;

        if ($company) {
            $company->addEmployee($this);
        }
    }
}

我认为这比使用@PostDeserialize更自然,因为您的代码中可能已经有了一些这样的方法。此外,它以两种方式确保合同,因此如果您从Employee开始,您将获得相同的结果。

答案 1 :(得分:0)

关于反序列化对象时手动设置引用的内容是什么?像这样:

class Company { 

    ....

    @PostDeserialize
    public function setReferences()
    {
        foreach( $this->employees as $employee ){
            $employee->setCompany( $this );
        }
    }
}

答案 2 :(得分:0)

保持JSON实体尽可能简单是一种很好的做法!如果您必须处理这类问题,那么现在是重新考虑您的数据模型的时刻!

此外,您是否考虑过使用HATEOAS(超媒体作为应用程序状态的引擎)是一个原则,应该使用超文本链接来创建更好的API导航。看起来像这样:

{
  "id": 711,
  "manufacturer": "bmw",
  "model": "X5",
  "seats": 5,
  "drivers": [
   {
    "id": "23",
    "name": "Stefan Jauker",
    "links": [
     {
     "rel": "self",
     "href": "/api/v1/drivers/23"
    }
   ]
  }
 ]
}