json encode is not working with array of objects

2020-02-26 07:35发布

问题:

I want to convert array of objects to json encoding, I make like this

$allVisits = $mapper->getAllVisits($year, $month);
echo json_encode($allVisits);

and here's is getAllVisists method

 function getAllVisits($year, $month) {
    $where = array(
        'year = ?' => $year,
        'month = ?' => $month
    );
     $resultSet = $this->getDbTable()->fetchAll( $where);
    $visitsEntries = array();
    foreach ($resultSet as $row) {

        $entry = new Visits_Model_Visit();
        $entry->setId($row->visit_id)
                ->setDay($row->day)
                ->setDate($row->date)
                ->setTarget($row->target)
                ->setStatus($row->visit_status)
                ->setTime($row->visit_time);

        $visitsEntries[] = $entry;
    }
    return $visitsEntries;
}

when I echo the size of $allVisits it return correct number of records, but in js the values are received empty like this [{},{},{},{}]

Edit

When I print_r($allVisists) brfore encoding it it returns

Array
(
    [0] => Visits_Model_Visit Object
        (
            [day:private] => sunday
            [date:private] => 2012-03-06
            [target:private] => شسي
            [id:private] => 1
            [status:private] => 0
            [time:private] => 12:00:00
        )

    [1] => Visits_Model_Visit Object
        (
            [day:private] => sunday
            [date:private] => 2012-03-06
            [target:private] => clinnics
            [id:private] => 4
            [status:private] => 0
            [time:private] => 00:00:00
        )

    [2] => Visits_Model_Visit Object
        (
            [day:private] => Tuesday
            [date:private] => 2012-03-06
            [target:private] => clinnics
            [id:private] => 5
            [status:private] => 0
            [time:private] => 00:00:00
        )

    [3] => Visits_Model_Visit Object
        (
            [day:private] => Wednesday
            [date:private] => 2012-03-28
            [target:private] => ??????? ???????
            [id:private] => 7
            [status:private] => 0
            [time:private] => 12:00:00
        )

)

回答1:

You are using json_encode with objects that don't have any public members. json_encode only works on the members it can "see", that's why those are empty.

Since PHP 5.4 you can make use of the JsonSerializable interface to control which data will be offered for json_encode, e.g.:

class Visits_Model_Visit implements JsonSerializable {
    ...
    public function jsonSerialize() {
        return (object) get_object_vars($this);
    }
    ...
}

If you are below 5.4 you can also implement that function w/o extending from the interface and then assigning the correct value manually:

$visitsEntries[] = $entry->jsonSerialize();

Hope this helps.



回答2:

Are the properties private or protected for the object? If so, json encode can't see them inside the object. I get around this by creating a 'toJson' method in my objects that I need to serialize into json. In this method, I walk the objects properties and manually construct a generic object, that I pass to json_encode. Then I return the Json string from this method.

Do not just make all your object properties public!!!!



回答3:

As Ray says if your class properties are protected or private, these will not be jsoned.

Since PHP 5.4 instead of using the commented toJson method, you have the ability to specify which data will be serialized implementing the JsonSerializable interface, so json_encode knows how to work on this.

/* PHP >= 5.4 only */
class Visits_Model_Visit implement JsonSerializable {
    public function jsonSerialize()
    {
        return array(
             'day' => $this->day,
             'date' => $this->date,
             'target' => $this->target,
             'id' => $this->id,
             'status' => $this->status,
        );
    }
}


回答4:

By default, json_encode() only serializes public properties of an object. Making all properties you want serialized public is NOT the solution! PHP 5.4 and later has the JsonSerializable interface, but I propose a straightforward solution for earlier versions of PHP.

Since JsonSerializable is only part of PHP 5.4 and later, create it yourself.

if (!interface_exists('JsonSerializable')) {
   interface JsonSerializable {
      public function jsonSerialize();
   }
}

That wasn't so hard, was it? Now we can implement JsonSerializable without worrying about what version of PHP we are using!

class Visits_Model_Visit implements JsonSerializable {
    ...
    // Only put properties here that you want serialized.
    public function jsonSerialize() {
        return Array(
           'day'    => $this->day,
           'date'   => $this->date,
           'target' => $this->target,
           'id'     => $this->id,
           'status' => $this->status,
           'obj'    => $this->obj->jsonSerialize(), // example for other objects
           'time'   => $this->time
        );
    }
    ...
}

Now you can just call jsonSerialize() to get an associative array that you can encode with json_encode().

    ...
    $entry = new Visits_Model_Visit();
    $entry->setId($row->visit_id)
          ->setDay($row->day)
          ->setDate($row->date)
          ->setTarget($row->target)
          ->setStatus($row->visit_status)
          ->setTime($row->visit_time);

    $visitsEntries[] = $entry->jsonSerialize();
    ...

You may then call json_encode($visitsEntries) to get your desired result.

[
   {
      "day":"sunday",
      "date":"2012-03-06",
      "target":"\u0634\u0633\u064a",
      "id":1,
      "status":0,
      "time":"12:00:00"
   },
   {
      "day":"sunday",
      "date":"2012-03-06",
      "target":"clinnics",
      "id":4,
      "status":0,
      "time":"00:00:00"
   },
   ...
]


回答5:

For those who are looking for simple answer, unlike other complicated answers my is piece of art:

json_encode(array(
    Protocol::PARAM_CODE => Protocol::CODE_SUCCESS,
    Protocol::PARAM_USER => (object)$user->jsonSerialize()
));

Even when $user->jsonSerialize() outputs stdObject, json_encode is so dumb, it has no idea it is object so you have to state that explicitly with casting it to (object) - don't you love PHP for it's simplicity?