1

A price object has three properties,

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

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

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

When serializing this object to json via the symfony2 Symfony\Component\HttpFoundation\JsonResponse, it will look like:

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

I want the \DateTime to be formatted as simply a string:

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

How to get this done is not the scope of the question, as I currently handle this case in the object's constructor:

/**
 * 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);
    }
}

yet it doesn't feel entirely right, and I am curious if I could configure the serialize process differently, in the sense, instead of coding my representation, modify the way the object is serialized.

Reasoning is to have all \DateTime objects serialized that are serialized wherever in an to-be-serialized object in a same specific way, without duplicating logic. (I guess I could put the handling in an abstract class or somewhere similar, yet extending objects also has its pitfalls)

Basically:

Is there a catch an onserialize "event" where I can add some logic, or am I better off looking into JMSSerializer?

1
  • 2
    just have your class implement the JsonSerializable class and create a method named jsonSerialize that returns an array of the data you want serialized by the json_encode() function Commented Nov 9, 2015 at 18:02

2 Answers 2

3

I don't know why I didn't submit this as the answer. Since PHP 5.4.0 a JsonSerializable library class is shipped with the PHP install. You can implement this class on your own and create a method named jsonSerialize that will be called whenever json_encode() is called with the class as the argument. A solution to your predicament could be similar to this:

<?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()));
Sign up to request clarification or add additional context in comments.

Comments

1

So you have 3 options:

  • Use the JsonSerializable interface like @iam-coder proposed.
  • Use a full-blown serializer like JMS (can be slow).
  • Use a transformer, the plus side of this is that your output is decoupled from your data, and you can change and test each component on it's own.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.