Verwenden von json_encode für Objekte in PHP (unabhängig vom Umfang)

75

Ich versuche, Listen von Objekten als json auszugeben und möchte wissen, ob es eine Möglichkeit gibt, Objekte nutzbar zu machen json_encode. Der Code, den ich habe, sieht ungefähr so ​​aus

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

Im Moment durchlaufe ich nur das Array von Benutzern und exportiere sie einzeln in Arrays json_encode, um sie für mich in verwendbaren JSON zu verwandeln. Ich habe bereits versucht, die Objekte iterierbar zu machen, aber ich json_encodescheine sie trotzdem zu überspringen.

edit : hier ist der 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*
    }
  }
}

und hier ist, was json_encode mir gibt:

php > echo json_encode($a);
{}

Am Ende hatte ich genau das:

    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).'}';   
        }   
    }   

Es nimmt Arrays voller dieser Objekte oder nur einzelner Instanzen und verwandelt sie in json - ich verwende es anstelle von json_encode. Ich bin mir sicher, dass es Orte gibt, an denen ich es verbessern könnte, aber ich hatte gehofft, dass json_encode anhand seiner exponierten Schnittstellen erkennen kann, wann ein Objekt durchlaufen werden muss.

A. Wütend
quelle
Was ist die Ausgabe von var_dump($related)und echo json_encode($related)?
BoltClock
'Objekte' sind per Definition nicht iterierbar.
Jondavidjohn
Mit iterierbar meine ich, dass die Objekte die Schnittstelle IteratorAggregate implementieren und dass ich sie mit einem einfachen foreach durchlaufen kann.
A. Rager

Antworten:

7

In RedBeanPHP 2.0 gibt es eine Massenexportfunktion, die eine gesamte Sammlung von Beans in Arrays umwandelt. Dies funktioniert mit dem JSON-Encoder.

json_encode( R::exportAll( $beans ) );
Gabor de Mooij
quelle
Wenn Sie in RB 2.0 eine Bean in eine Zeichenfolge umwandeln, erhalten Sie außerdem die JSON-Darstellung.
Gabor de Mooij
150

Alle Eigenschaften Ihres Objekts sind privat. aka ... nicht verfügbar außerhalb des Bereichs ihrer Klasse.

Lösung für PHP <5.4

Wenn Sie Ihre privaten und geschützten Objekteigenschaften serialisieren möchten, müssen Sie eine JSON-Codierungsfunktion in Ihrer Klasse implementieren , die json_encode()eine für diesen Zweck erstellte Datenstruktur verwendet.

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()                
        ));
    }
    ...
}

Lösung für PHP> = 5.4

Verwenden Sie die neue JsonSerializableSchnittstelle, um Ihre eigene JSON-Darstellung bereitzustellen, die von verwendet werden solljson_encode

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

Eine detailliertere Beschreibung

jondavidjohn
quelle
2
json_encode () gibt nur "{}" aus, wenn ich diese Objekte übergebe. Es geht leider nicht darum, meine Arrays assoziativ zu definieren oder nicht.
A. Rager
Ich glaube, er spricht über das Array $ a-> properties, das anscheinend die Daten enthält, nach denen Sie suchen. Da dies eine private Variable ist, wird sie von json_encode () ignoriert und veranlasst json_encode (), '{}' auszugeben, wie Sie es beschreiben.
cmendoza
Ich hatte gehofft, dass json_encode () exponierte Methoden sehen kann, um ein Verhalten zu definieren, an dem Objekte ohne extern zugängliche Eigenschaften beteiligt sind. Es scheint, dass dies noch nicht möglich ist, deshalb habe ich stattdessen eine Funktion geschrieben, um diese Objektlisten rekursiv zu verarbeiten.
A. Rager
Sie können eine andere Lösung unter jrgns.net/content/…
Jrgns
Der Vollständigkeit halber können Sie, wie von @Jrgns erwähnt, zurückkehren get_object_vars( $this ); , um alle Eigenschaften zu sichern .
pcarvalho
44

In PHP> = 5.4.0 gibt es eine neue Schnittstelle zum Serialisieren von Objekten in JSON: JsonSerializable

Implementieren Sie einfach die Schnittstelle in Ihrem Objekt und definieren Sie eine JsonSerializableMethode, die bei Verwendung aufgerufen wird json_encode.

Die Lösung für PHP> = 5.4.0 sollte also ungefähr so ​​aussehen:

class JsonObject implements JsonSerializable
{
    // properties

    // function called when encoded with json_encode
    public function jsonSerialize()
    {
        return get_object_vars($this);
    }
}
ilanco
quelle
Um das JSON-Array json_encode($result)$result = get_object_vars($this);
wiederzugeben
Dies sollte die akzeptierte Antwort sein - funktioniert automatisch mit jeder Klasse, da get_object_vars alle Eigenschaften iteriert.
Nico Westerdale
Ich bin nicht sicher, was sich in PHP oder meinem Code geändert hat, aber egal, was ich in letzter Zeit mache, get_object_vars($this)ignoriert den Umfang von $ this und weigert sich, die privaten Mitglieder des Objekts zu überprüfen. Wenn alle Mitglieder privat sind, erhalte ich ein leeres Array-Ergebnis. Ich benutze PHP 5.6.31. Gibt es eine Voraussetzung, get_object_vars($this)um den Umfang zu erkennen?
JasonGabler
Ich glaube nicht, dass sich etwas geändert hat get_object_vars. Es wurden immer nur Eigenschaften zurückgegeben, die zugänglich waren. Wenn Sie also von innerhalb eines Objekts aus anrufen, erhalten Sie alle Privaten und von außerhalb nicht. Siehe php.net/get_object_vars#example-6296
Lode
4

Der folgende Code hat bei mir funktioniert:

public function jsonSerialize()
{
    return get_object_vars($this);
}
user2944142
quelle
2

Ich habe dies noch nicht erwähnt, aber Bohnen haben eine eingebaute Methode namens getProperties().

Also, um es zu benutzen:

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

Dies gibt aus:

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

Gehen Sie jetzt noch einen Schritt weiter. Wenn wir eine Reihe von Bohnen haben ...

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

... dann könnten wir folgendes tun:

  • Durchlaufen Sie das Array mit einer foreachSchleife.

  • Ersetzen Sie jedes Element (eine Bean) durch ein Array der Bean-Eigenschaften.

Also das...

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

print json_encode($series);

... gibt Folgendes aus:

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

Hoffe das hilft!

chrisfargen
quelle
1

Normalerweise füge ich meinen Objekten eine kleine Funktion hinzu, mit der ich in Array, JSON oder XML sichern kann. Etwas wie:

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

so oder so, get_object_vars()ist wahrscheinlich nützlich für Sie.

Phönix
quelle
Ich kann einfach json_encode verwenden ($ thing-> export ()); um mir den json zu geben, den ich will, aber das funktioniert nicht so gut, wenn ich Arrays von ihnen habe.
A. Rager
Dann können Sie das Array von Objekten in ein Array von Arrays mit so etwas wie konvertieren for each($objArray as $key => $obj){$arrArray[$key] = $obj->export());} json_encode($arrArray);oder eine array_map mit get_object_vars () erstellen.
Phoenix
0
$products=R::findAll('products');
$string = rtrim(implode(',', $products), ',');
echo $string;
Asahajit
quelle
0

Hier ist mein Weg:

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;
}
Andrei
quelle
-1

Für ein Array von Objekten habe ich so etwas verwendet, während ich der benutzerdefinierten Methode für PHP <5.4 gefolgt bin:

$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);
Greg
quelle