如何在 Symfony 3 中使用回调或任何其他方法规范化给定的 属性?

How to normalize a given property using callback or any other method in Symfony 3?

假设我收到来自 API 电话的以下响应:

[
  {
    "AgreementNumber": 20266,
    "StartDate": "2005-07-01T00:00:00",
    "EndDate": "2006-06-30T00:00:00",
    "AgreementTypeId": 1,
    "CfProgramLevelId": 2,
    "TamFlag": 0,
    "ParentAgreementNumber": null,
    "DistributorId": 16,
    "CustomerSiteId": 232,
    "RowId": 100,
    "Source": "Wonderware",
    "ActiveFlg": 1
  },
  ...
]

我正在将该结果映射到 Agreement 实体,如下所示:

$propertyNameConverter = new PropertyNameConverter();
$encoders              = [new XmlEncoder(), new JsonEncoder()];
$normalizers           = [new ObjectNormalizer(null, $propertyNameConverter), new ArrayDenormalizer(),];
$serializer            = new Serializer($normalizers, $encoders);

$entities = $serializer->deserialize($data, "QuoteBundle\Entity\Agreement[]", 'json');

实体是这样的:

class Agreement
{
    /**
     * @var \DateTime
     * @ORM\Column(name="StartDate", type="string", nullable=false)
     */
    private $startDate;

    /**
     * @ORM\OneToOne(targetEntity="QuoteBundle\Entity\AgreementType")
     * @ORM\JoinColumn(name="AgreementTypeID", referencedColumnName="AgreementTypeID")
     */
    private $agreementType;

    /**
     * @param \DateTime $startDate
     */
    public function setStartDate(\DateTime $startDate)
    {
        $this->startDate = $startDate;
    }

    /**
     * @param AgreementType $agreementType
     */
    public function setAgreementType(AgreementType $agreementType)
    {
        $this->agreementType = $agreementType;
    }
}

每次尝试映射数据时,我都会收到以下错误:

Expected argument of type "DateTime", "string" given

这很好,因为我期待 DateTime 作为 startDate。这里的解决方案是在将数据映射到实体之前转换|规范化数据。

我已阅读 here 但我无法找到如何将此 "callback" 应用于给定的 属性 因为该示例是一个简单的用例而不是一个复杂的用例。

我试过以下代码:

$dateTimeNormalizer = new GetSetMethodNormalizer();
$dateTimeCallback   = function ($dateTime) {
    return $dateTime instanceof \DateTime ? $dateTime->format(\DateTime::ATOM) : '';
};

$dateTimeNormalizer->setCallbacks(['startDate' => $dateTimeCallback, 'endDate' => $dateTimeCallback]);

$normalizers = [
    new ObjectNormalizer(null, $propertyNameConverter),
    new ArrayDenormalizer(),
    $dateTimeNormalizer,
];

$serializer = new Serializer($normalizers, $encoders);

但是没有用,因为我仍然遇到与上述相同的错误。我知道有一个 DateTimeNormalizer 但将它作为新条目添加到 $normalizers 数组并不能使其正常工作。结果与上面的意思相同。

我还需要一个回调来将 属性 AgreementTypeId 规范化为 agreementType 因为我很确定它也会失败。 (实际上目前没有被映射,我认为问题是因为名称不匹配)

谁能帮我解决这个问题?

答案是下面几行 - Recursive Denormalization and Type Safety

    $encoder = new JsonEncoder();

    $normalizer = new ObjectNormalizer(null, null, null, new ReflectionExtractor());
    $serializer = new Serializer(array(new DateTimeNormalizer(), $normalizer, new ArrayDenormalizer()), [$encoder]);

    $entities = $serializer->deserialize($data, "QuoteBundle\Entity\Agreement[]", 'json');