Використання json_encode на об'єктах у PHP (незалежно від сфери дії)


75

Я намагаюся вивести списки об'єктів як json і хотів би знати, чи є спосіб зробити об'єкти придатними для використання json_encode? Код, який я отримав, виглядає приблизно так

$related = $user->getRelatedUsers();
echo json_encode($related);

Зараз я просто переглядаю масив користувачів та індивідуально експортую їх у масиви, json_encodeщоб перетворитись на корисний для мене json. Я вже намагався зробити об'єкти ітерабельними, але, json_encodeздається, все одно їх пропускаю.

редагувати : ось var_dump ();

php > var_dump($a);
object(RedBean_OODBBean)#14 (2) {
  ["properties":"RedBean_OODBBean":private]=>
  array(11) {
    ["id"]=>
    string(5) "17972"
    ["pk_UniversalID"]=>
    string(5) "18830"
    ["UniversalIdentity"]=>
    string(1) "1"
    ["UniversalUserName"]=>
    string(9) "showforce"
    ["UniversalPassword"]=>
    string(32) ""
    ["UniversalDomain"]=>
    string(1) "0"
    ["UniversalCrunchBase"]=>
    string(1) "0"
    ["isApproved"]=>
    string(1) "0"
    ["accountHash"]=>
    string(32) ""
    ["CurrentEvent"]=>
    string(4) "1204"
    ["userType"]=>
    string(7) "company"
  }
  ["__info":"RedBean_OODBBean":private]=>
  array(4) {
    ["type"]=>
    string(4) "user"
    ["sys"]=>
    array(1) {
      ["idfield"]=>
      string(2) "id"
    }
    ["tainted"]=>
    bool(false)
    ["model"]=>
    object(Model_User)#16 (1) {
      ["bean":protected]=>
      *RECURSION*
    }
  }
}

і ось що мені дає json_encode:

php > echo json_encode($a);
{}

Я закінчив саме цим:

    function json_encode_objs($item){   
        if(!is_array($item) && !is_object($item)){   
            return json_encode($item);   
        }else{   
            $pieces = array();   
            foreach($item as $k=>$v){   
                $pieces[] = "\"$k\":".json_encode_objs($v);   
            }   
            return '{'.implode(',',$pieces).'}';   
        }   
    }   

Він бере масиви, заповнені цими об’єктами, або просто одиничні екземпляри, і перетворює їх на json - я використовую його замість json_encode. Я впевнений, що є місця, де я міг би зробити це кращим, але я сподівався, що json_encode зможе визначити, коли здійснювати ітерацію через об'єкт на основі його відкритих інтерфейсів.


Що таке вихід var_dump($related)і echo json_encode($related)?
BoltClock

"об'єкти" за визначенням не піддаються ітерації.
jondavidjohn

Під ітерацією я маю на увазі, що об’єкти реалізують інтерфейс IteratorAggregate і що я можу перебирати їх за допомогою простого foreach.
A. Rager

Відповіді:


8

У RedBeanPHP 2.0 є функція масового експорту, яка перетворює всю колекцію зерен на масиви. Це працює з кодером JSON ..

json_encode( R::exportAll( $beans ) );

Крім того, у RB 2.0, якщо ви приведете компонент до рядка, ви отримаєте представлення JSON.
Gabor de Mooij

152

Усі властивості вашого об’єкта є приватними. він же ... недоступний поза сферою їхнього класу.

Рішення для PHP> = 5.4

Використовуйте новий JsonSerializableінтерфейс, щоб забезпечити власне представлення json, яке буде використовуватисяjson_encode

class Thing implements JsonSerializable {
    ...
    public function jsonSerialize() {
        return [
            'something' => $this->something,
            'protected_something' => $this->get_protected_something(),
            'private_something' => $this->get_private_something()
        ];
    }
    ...
}

Рішення для PHP <5.4

Якщо ви хочете серіалізувати свої приватні та захищені властивості об’єкта, вам доведеться реалізувати функцію кодування JSON всередині вашого класу, яка використовує json_encode()структуру даних, яку ви створюєте для цієї мети.

class Thing {
    ...
    public function to_json() {
        return json_encode(array(
            'something' => $this->something,
            'protected_something' => $this->get_protected_something(),
            'private_something' => $this->get_private_something()                
        ));
    }
    ...
}

Більш детальний опис


2
json_encode () просто видає "{}", коли я передаю йому ці об'єкти. Справа не в тому, щоб мої масиви були визначені асоціативними чи ні, на жаль.
A. Rager

Я вважаю, що він говорить про масив властивостей $ a->, який, схоже, містить дані, які ви шукаєте. Оскільки це приватна змінна, вона буде проігнорована json_encode () і призведе до виведення json_encode (), як ви описуєте.
cmendoza

Я сподівався, що json_encode () зможе побачити відкриті методи для визначення якоїсь поведінки за участю об'єктів без зовнішніх властивостей. Здається, цього ще неможливо зробити, тому я написав функцію для рекурсивної обробки цих списків об’єктів.
A. Rager

Ви можете побачити інше рішення за адресою jrgns.net/content/…
Jrgns

для повноти, як згадував @Jrgns, ви можете повернутися, get_object_vars( $this ); щоб скинути всі властивості.
pcarvalho

46

У PHP> = 5.4.0 є новий інтерфейс для серіалізації об'єктів до JSON: JsonSerializable

Просто впровадьте інтерфейс у свій об’єкт і визначте JsonSerializableметод, який буде викликаний під час використання json_encode.

Тож рішення для PHP> = 5.4.0 має виглядати приблизно так:

class JsonObject implements JsonSerializable
{
    // properties

    // function called when encoded with json_encode
    public function jsonSerialize()
    {
        return get_object_vars($this);
    }
}

Щоб повторити масив JSON, поверніться json_encode($result)куди$result = get_object_vars($this);
CyberEd

Це має бути прийнятою відповіддю - автоматично працює з будь-яким класом, оскільки get_object_vars буде повторювати всі властивості.
Ніко Вестердейл

Я не впевнений, що змінилося в PHP або в моєму коді, але незалежно від того, що я роблю останнім часом, get_object_vars($this)ігнорує обсяг $ this і відмовляється від самоаналізу на приватних членах об'єкта. Коли всі учасники приватні, я отримую порожній результат масиву. Я використовую PHP 5.6.31. Чи існує якась вимога для get_object_vars($this)розпізнавання сфери застосування?
JasonGabler

Я не думаю, що щось змінилося get_object_vars. Це завжди було лише повернення властивостей, які були доступні. Таким чином, при дзвінку зсередини об’єкта ви отримаєте всіх рядових, а зовні - ні. Дивіться php.net/get_object_vars#example-6296
Лоде


2

Я ще не бачив цього згаданого, але квасоля має вбудований метод, який називається getProperties().

Отже, щоб використовувати його:

// What bean do we want to get?
$type = 'book';
$id = 13;

// Load the bean
$post = R::load($type,$id);

// Get the properties
$props = $post->getProperties();

// Print the JSON-encoded value
print json_encode($props);

Це виводить:

{
    "id": "13",
    "title": "Oliver Twist",
    "author": "Charles Dickens"
}

Тепер зробіть крок далі. Якщо ми маємо масив квасолі ...

// An array of beans (just an example)
$series = array($post,$post,$post);

... тоді ми могли б зробити наступне:

  • Прокрутіть цикл через масив foreach.

  • Замініть кожен елемент (bean) масивом властивостей bean.

Отож це ...

foreach ($series as &$val) {
  $val = $val->getProperties();
}

print json_encode($series);

... виводить це:

[
    {
        "id": "13",
        "title": "Oliver Twist",
        "author": "Charles Dickens"
    },
    {
        "id": "13",
        "title": "Oliver Twist",
        "author": "Charles Dickens"
    },
    {
        "id": "13",
        "title": "Oliver Twist",
        "author": "Charles Dickens"
    }
]

Сподіваюся, це допомагає!


1

Я зазвичай включаю невелику функцію в свої об'єкти, яка дозволяє мені скидати масив або json або xml. Щось на зразок:

public function exportObj($method = 'a')
{
     if($method == 'j')
     {
         return json_encode(get_object_vars($this));
     }
     else
     {
         return get_object_vars($this);
     }
}

в будь-якому випадку, get_object_vars()це, мабуть, корисно для вас.


Я можу просто використовувати json_encode ($ thing-> export ()); щоб дати мені потрібний json, але це не працює так добре, коли у мене є їх масиви.
A. Rager

Потім ви можете перетворити масив об'єктів у масив масивів чимось на зразок, for each($objArray as $key => $obj){$arrArray[$key] = $obj->export());} json_encode($arrArray);або ви можете зробити карту масиву за допомогою get_object_vars ().
Фенікс,


0

Ось мій шлях:

function xml2array($xml_data)
{
    $xml_to_array = [];

    if(isset($xml_data))
    {
        if(is_iterable($xml_data))
        {
            foreach($xml_data as $key => $value)
            {
                if(is_object($value))
                {
                    if(empty((array)$value))
                    {
                        $value = (string)$value;
                    }
                    else
                    {
                        $value = (array)$value;
                    }
                    $value = xml2array($value);
                }
                $xml_to_array[$key] = $value;
            }
        }
        else
        {
            $xml_to_array = $xml_data;
        }
    }

    return $xml_to_array;
}

-1

для масиву об'єктів я використовував щось подібне, дотримуючись користувацького методу для php <5.4:

$jsArray=array();

//transaction is an array of the class transaction
//which implements the method to_json

foreach($transactions as $tran)
{
    $jsArray[]=$tran->to_json();
}

echo json_encode($jsArray);
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.