2010-05-17 2 views
10

Ich konvertiere von JSON zu Objekt und von Objekt zu Array. Es ist nicht das, was ich erwartet habe. Kannst du es mir erklären?JSON-Objektkonvertierungsfrage

$json = '{"0" : "a"}'; 
$obj = json_decode($json); 
$a = (array) $obj; 
print_r($a); 
echo("a0:".$a["0"]."<br>"); 

$b = array("0" => "b"); 
print_r($b); 
echo("b0:".$b["0"]."<br>"); 

Der Ausgang ist hier:

Array ([0] => a) a0: 
Array ([0] => b) b0:b 

Ich würde a0 zu erwarten: a am Ende der ersten Zeile.

Edit: Nachdem die Antworten Lese erweiterte ich den Code, die das Verhalten deutlicher macht:

//extended example 
$json = '{"0" : "a"}'; 
$obj = json_decode($json); 
$a = (array) $obj; 
var_export($a); 
echo("a0:".$a["0"]."<br>"); //this line does not work, see the answers 
echo $obj->{"0"}."<br>"; //works! 

$json = '{"x" : "b"}'; 
$obj = json_decode($json); 
$b = (array) $obj; 
var_export($b); 
echo("bx:".$b["x"]."<br>"); 

$c = array("1" => "c"); 
var_export($c); 
echo("c1:".$c["1"]."<br>"); 

$d = array("0" => "d"); 
var_export($d); 
echo("d0:".$d["0"]."<br>"); 

Ausgabe von erweiterten Beispiel:

array ('0' => 'a',)a0: 
a 
array ('x' => 'b',)bx:b 
array (1 => 'c',)c1:c 
array (0 => 'd',)d0:d 
+0

es ist unglaublich, aber das ist was php tut%) ein Fehler? – zerkms

+0

zerkms: Ich bin froh, dass Sie das Verhalten bestätigen können. Nachdem ich es für eine Weile benutzt habe, erwarte ich nicht, dass es perfekt ist. Dies ist nicht seine primäre Stärke. Aber vielleicht können wir verstehen, was passiert. OP karlthorwald - aka – user89021

+0

@karlthorwald: Das ist sehr seltsam, ich nehme an, das ist ein Fehler. Versuchen Sie es über PHP.net zu übermitteln. –

Antwort

4

Es gibt weitere Informationen in this older question. Die kurze Version ist, dass properties auf PHP-Objekte/Klassen die gleichen folgen naming convention as variables. Eine numerische Eigenschaft ist für ein PHP-Objekt ungültig, daher gibt es keine klare Regel, was passieren sollte, wenn ein Objekt aus einer anderen Sprache (json/javascript) mit einem numerischen Schlüssel serialisiert wird. Während es Ihnen offensichtlich erscheint, was mit dem oben Gesagten passieren sollte, sieht jemand mit einer anderen Ausrichtung das Verhalten von PHP in diesem Fall als vollkommen gültig und bevorzugt.

Also, es ist eine Art Bug, aber mehr ein undefinierter Bereich der Spezifikation ohne klare Antwort, also erwarten Sie nicht, dass sich das Verhalten ändert, um Ihren Geschmack zu treffen, und wenn es sich ändert, erwarten Sie das nicht ändern, um dauerhaft zu sein.

, um einige der Fragen in den Kommentaren befassen, sollten Sie diese

header('Content-Type: text/plain'); 
$json = '{"0" : "a"}'; 
$obj = json_decode($json); 
$a = (array) $obj; 
var_dump($a); 
var_dump(array(0=>'a')); 
var_dump(array('0'=>'a')); 

die

array(1) { 
    ["0"]=> 
    string(1) "a" 
} 
array(1) { 
    [0]=> 
    string(1) "a" 
} 
array(1) { 
    [0]=> 
    string(1) "a" 
} 

Ein Array mit einem einzelnen String-Schlüssel Null wie diese etwas Ausgabe wird keine gültige PHP bauen. Wenn Sie versuchen, ein PHP zu erstellen, wird die Null zu einem int für Sie. Wenn Sie PHP bitten, eine Umwandlung durchzuführen, für die es keine Definition gibt, wird am Ende ein Array mit einem String-Schlüssel erstellt (wegen der unklaren Regeln, was hier passieren soll).

Während es offensichtlich ist, dass dies ein "falsches" Verhalten von PHP ist, ist es nicht leicht, das richtige Verhalten in einer schwach typisierten Sprache zu definieren.

+0

Noch, wenn Sie 'print_r()' das '$ a', nachdem es als Array gegossen wurde, können Sie deutlich sehen, dass der Index' 0' nicht gelöscht wurde. –

+1

ja. stimmte mit @Alix überein. Die Erklärung in http://stackoverflow.com/questions/1869812/casing-an-array-with-numeric-keys-as-an-object funktioniert für Objekte. Da wir aber das Objekt explizit auf Array setzen, erwarten wir, dass es auf reguläre Weise funktioniert. Selbst wenn das neue Array diesen "ungültigen Schlüssel" nicht enthalten würde, kann es auch erklärt werden (wegen der fehlerhaften Eigenschaft des Objekts). aber semi-funktionale Array sieht sehr fehlerhaft aus. – zerkms

+1

Aktualisierte Frage, um andere Kommentare zu adressieren. Im Fall von $ a wirfst du ** ein bereits ungültiges Objekt ** als ein Array, so dass du ein unbestimmtes Verhaltensgebiet betrittst und alle Wetten aus sind. Im Falle von $ b wandelt PHP automatisch die "0" als int um ein gültiges Array zu erzeugen. Ich stimme zu, dass es ein merkwürdiges Verhalten ist, aber Sie enden mit ähnlichen seltsamen Verhaltensweisen in jeder Sprache, die auf starkes Tippen verzichtet. –

1

Sie können es nur als Zugang Objekt (stdClass) und nicht ein Array:

Dies ist am einfachsten, da Ihr JavaScript ein Objekt war ({}) und nicht zuerst ein Array [].

Alternativ können Sie tun dies

$arr = json_decode($json, true); 

Der zweite optionale Parameter es Ausgabe ein assoziatives Array macht. http://us.php.net/json_decode

+0

Sie haben die 3. Zeile verpasst, in der das Objekt in ein Array konvertiert wurde. Ihre Antwort erklärt nicht, warum wir das Element in var_dump() sehen können, aber nicht darauf zugreifen können. Die allgemeine Frage ist über 'Objekt-> Array'-Konvertierung und nicht darüber, wie man mit' json_decode' arbeitet. – zerkms

+0

philfreo danke. Das hilft mir, mit meiner Codierung fortzufahren. aber ich halte die Frage jetzt offen und vielleicht erklärt jemand das unerwartete Verhalten, das ich gefunden habe. OP karlthorwald - aka – user89021

1

Warum machst du das? Weißt du, dass du die JSON dekodierten Werte direkt als Array haben kannst?

$arr = json_decode($json, true); 

echo '<pre>'; 
print_r($arr); 
echo '</pre>'; 
+0

Das rechtfertigt die Ergebnisse sowieso nicht ;-) Geht das? – zerkms

1
Array ([0] => a) a0: 
Array ([0] => b) b0:b 

PHP ist nicht hilfreich print_r greift wieder an!

Das erste Array einen ganzzahligen 0 Schlüssel, weil der (array) Guss sie in eine flache Liste artige Anordnung zu drehen versucht.

Das zweite Array behält den assoziativen Array-artigen String-Schlüssel '0' bei, mit dem Sie ihn erstellt haben.

Verwenden Sie var_export anstelle von print_r und Sie können den Unterschied leichter sehen.

+0

'var_dump', eigentlich – zerkms

+0

Es hilft viel zu wissen, dass print_r nicht gut funktioniert. Noch immer var_export zeigt einen String-Schlüssel an (siehe das erweiterte Beispiel in der Frage) – user89021

+0

@zerkms: ['var_export'] (http://php.net/manual/en/function.var-export.php), eigentlich –

1

Nun, das Problem existiert nur, wenn das ursprüngliche Objekt Eigenschaften hat, die nicht erlaubt sind [aka Eigenschaften, die numerisch sind]. Dies hängt nicht mit json_encode/decode zusammen, sondern mit jeder Operation, die die Konvertierung von Objekten in Array umfasst. Alle Integer-Schlüssel werden unzugänglich gemacht.

http://www.php.net/manual/en/language.types.array.php - wo es heißt: Wenn ein Objekt in ein Array konvertiert wird, ist das Ergebnis ein Array, dessen Elemente die Eigenschaften des Objekts sind. Die Schlüssel sind die Namen der Mitgliedsvariablen, mit einigen bemerkenswerten Ausnahmen: Integer-Eigenschaften sind nicht zugänglich; Bei privaten Variablen wird der Klassenname dem Variablennamen vorangestellt. Für geschützte Variablen wird dem Variablennamen ein '*' vorangestellt. Diese vorangestellten Werte haben auf jeder Seite null Byte.