2010-05-17 15 views
10

Konwertuję z JSON na obiekt i z obiektu na tablicę. Nie tego się spodziewałem, czy możesz mi to wytłumaczyć?Pytanie o konwersję obiektu JSON

$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>"); 

Wyjście tutaj jest:

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

Liczyłam A0: a na końcu pierwszego wiersza.

Edit: Po przeczytaniu odpowiedzi I rozszerzony kod, który sprawia, że ​​zachowanie bardziej jasne:

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

Output rozszerzonej przykład:

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

To niewiarygodne, ale to właśnie php ma%) błąd? – zerkms

+0

zerkms: Cieszę się, że możesz potwierdzić zachowanie. Po używaniu go przez jakiś czas nie oczekuję, że php będzie idealny. To nie jest jego główna siła. Ale może możemy zrozumieć, co się dzieje. OP karlthorwald - aka – user89021

+0

@karlthorwald: To bardzo dziwne, zakładam, że to jakiś błąd. Spróbuj przesłać go przez PHP.net. –

Odpowiedz

4

Więcej informacji w this older question. Krótka wersja jest taka, że ​​properties na obiektach/klasach PHP występuje po tej samej naming convention as variables. Właściwość numeryczna jest niepoprawna w obiekcie PHP, więc nie ma jasnej reguły co do tego, co powinno się stać podczas serializacji obiektu z innego języka (json/javascript), który ma klucz numeryczny. Choć wydaje się oczywiste, co powinno się stać z powyższym, ktoś o innym nastawieniu widzi zachowanie PHP w tym przypadku jako całkowicie poprawne i preferowane.

Jest to rodzaj błędu, ale raczej nieokreślony obszar specyfikacji bez wyraźnej odpowiedzi, więc nie oczekuj, że zachowanie się zmieni, aby spełnić twoje upodobania, a jeśli to się zmieni, nie oczekuj, że zmienić się na stałe.

Aby rozwiązać niektóre kwestie w komentarzach, należy rozważyć tę

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

że wyjście będzie coś takiego

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

tablicę z zerem klucz pojedynczy ciąg nie jest prawidłowym PHP zbudować. Jeśli spróbujesz stworzyć jeden PHP, zamienisz zero w int dla ciebie. Kiedy poprosisz PHP o wykonanie obsady, nie ma definicji, kończy się to tworzeniem tablicy z kluczem (z powodu źle zdefiniowanych reguł dotyczących tego, co powinno się wydarzyć tutaj).

Podczas gdy jest oczywiste, że jest to "nieprawidłowe" zachowanie ze strony PHP, zdefiniowanie właściwego zachowania w słabo napisanym języku nie jest łatwe.

+0

Mimo to 'print_r()' '$ a' po tym, jak został rzucony jako tablica, wyraźnie widać, że indeks' 0' nie został usunięty. –

+1

tak. uzgodnione z @Alix. wyjaśnienie w http://stackoverflow.com/questions/1869812/casing-an-array-with-numeric-keys-as-an-object działa dla obiektów. ale ponieważ jawnie rzuciliśmy obiekt na tablicę, oczekujemy, że będzie działał w regularny sposób. nawet jeśli nowa tablica nie zawierałaby tego "zniekształconego klucza" - można to również wyjaśnić (z powodu nieprawidłowej właściwości obiektu). ale pół-funkcjonalna tablica wygląda bardzo błędnie. – zerkms

+1

Zaktualizowane pytanie dotyczące innych komentarzy. W przypadku $ a wyrzucasz ** już nieważny obiekt ** jako tablicę, więc wchodzisz na obszar niezdefiniowanego zachowania i wszystkie zakłady są wyłączone. W przypadku $ b PHP automatycznie rzuca "0" jako int, aby utworzyć poprawną tablicę. Zgadzam się, że to dziwne zachowanie, ale kończy się to dziwnymi zachowaniami w każdym języku, który unika silnego pisania. –

1

Można tylko dostęp go jako obiekt (stdClass) zamiast tablicy:

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

To jest najprostsze, ponieważ twój JavaScript był obiektem ({}), a nie tablicą [].

Alternatywnie, można to zrobić

$arr = json_decode($json, true); 

Drugi opcjonalny parametr sprawia, że ​​wyjściową tablicę asocjacyjną. http://us.php.net/json_decode

+0

Tęskniłeś za trzecim wierszem, w którym obiekt został przekonwertowany na tablicę. Twoja odpowiedź nie wyjaśnia, dlaczego możemy zobaczyć element w var_dump(), ale nie ma do niego dostępu. ogólne pytanie dotyczy konwersji "object-> array', a nie jak pracować z' json_decode' – zerkms

+0

philfreo dziękuję. to pomaga mi kontynuować moje kodowanie. ale mam teraz pytanie otwarte i być może ktoś wyjaśnia nieoczekiwane zachowanie, które znalazłem. OP karlthorwald - aka – user89021

1

Dlaczego to robisz? Czy wiesz, że możesz dekodować wartości JSON jako tablicę bezpośrednio?

$arr = json_decode($json, true); 

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

To i tak nie usprawiedliwia wyników ;-) Czy to prawda? – zerkms

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

Nieprzydatne PHP print_r ponownie atakuje!

Pierwsza tablica ma klucz całkowitoliczbowy 0, ponieważ obsada (array) próbuje przekształcić ją w płaską tablicę podobną do listy.

Druga tablica zachowuje skojarzony łańcuch znaków w postaci tablicy asocjacyjnej '0', z której została wykonana.

Użyj var_export zamiast print_r i łatwiej dostrzec różnicę.

+0

'var_dump', faktycznie – zerkms

+0

Bardzo pomaga to, że print_r nie działa dobrze. Nadal var_export pokazuje klucz ciąg (zobacz rozszerzony przykład w pytaniu) – user89021

+0

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

1

Cóż, problem występuje tylko wtedy, gdy początkowy obiekt ma właściwości, które są niedozwolone [także właściwości liczbowe]. Nie jest to związane z json_encode/decode, ale z dowolną operacją polegającą na konwersji z obiektów do tablicy. Wszystkie klucze całkowite będą niedostępne.

http://www.php.net/manual/en/language.types.array.php - gdzie jest wskazane, że: Jeśli obiekt jest konwertowany do tablicy, wynikiem jest tablica, której elementami są właściwości obiektu. Klucze są nazwami zmiennych składowych, z kilkoma ważnymi wyjątkami: właściwości liczb całkowitych są niedostępne; zmienne prywatne mają nazwę klasy poprzedzoną nazwą zmiennej; chronione zmienne mają "*" przedrostka nazwy zmiennej. Te wartości z góry mają po każdej stronie wartość zerową.