如何在json_encode期间配置对象的输出?

时间:2015-11-09 17:57:00

标签: php json symfony serialization

价格对象有三个属性,

/** @var float */
public $amount = 0.0;

/** @var string */
public $currency = '';

/**
 * @var \DateTime
 */
public $dueDate;

当通过symfony2 Symfony\Component\HttpFoundation\JsonResponse将此对象序列化为json时,它将如下所示:

{
  "price": {
    "amount": 235,
    "currency": "EUR",
    "dueDate": {
      "date": "2015-10-25 00:00:00.000000",
      "timezone": "UTC",
      "timezone_type": 3
    }
  }
}

我想将\ DateTime格式化为一个字符串:

"dueDate": "2015-10-22 00:00:00.000000"

如何完成这项工作不是问题的范围,因为我目前在对象的构造函数中处理这种情况:

/**
 * Price constructor.
 * @param float          $amount
 * @param string         $currency
 * @param \DateTime|null $dueDate
 */
public function __construct($amount = 0.0, $currency = "", $dueDate)
{
    $this->amount = $amount;
    $this->currency = $currency;
    $this->dueDate = $dueDate;;

    if ($dueDate instanceof \DateTime) {
        $this->dueDate = $dueDate->format(\DateTime::ATOM);
    }
}

然而它并没有感觉完全正确,我很好奇我是否能够以不同方式配置序列化过程,在某种意义上,而不是编码我的表示,修改对象的方式序列

推理是将序列化的所有\DateTime个对象以相同的特定方式序列化到待序列化对象中的任何位置,而不重复逻辑。 (我想我可以将处理放在抽象类或类似的地方,但扩展对象也有其缺陷)

基本上:

是否有捕获序列化"事件"在哪里我可以添加一些逻辑,或者我最好不要查看JMSSerializer

2 个答案:

答案 0 :(得分:2)

我不知道为什么我没有提交这个作为答案。从PHP 5.4.0开始,PHP安装附带了JsonSerializable库类。您可以自己实现此类,并创建一个名为jsonSerialize的方法,只要以类作为参数调用json_encode(),就会调用该方法。解决困境的方法可能类似于:

<?php
class Price implements JsonSerializable {
    private
        $amount
    ,   $currency
    ,   $dueDate
    ;
    /**
     * Price constructor.
     * @param float          $amount
     * @param string         $currency
     * @param \DateTime|null $dueDate
     */
    public function __construct($amount = 0.0, $currency = "", $dueDate = NULL)
    {
       $this->amount = $amount;
       $this->currency = $currency;
       $this->dueDate = $dueDate;
    }

    public function jsonSerialize(){
        return array(
            'amount' => $this->amount
        ,   'currency' => $this->currency
        ,   'dueDate' => $this->dueDate instanceof \DateTime ? $this->dueDate->format(\DateTime::ATOM) : $this->dueDate
    }
}

echo json_encode(new Price(235, "EUR", new DateTime()));

答案 1 :(得分:1)

所以你有3个选择:

  • 使用像@ iam-coder建议的JsonSerializable接口。
  • 使用像JMS这样的完整串行器(可能很慢)。
  • 使用transformer,这样做的好处是您的输出与数据分离,您可以更改并测试其上的每个组件。