2010-05-17 21 views
10

Estoy convirtiendo de JSON a objeto y de objeto a matriz. No es lo que esperaba, ¿puedes explicarme?Pregunta de conversión de objetos 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>"); 

La salida aquí es:

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

lo que habría esperado: una al final de la primera línea.

Editar: Después de leer las respuestas me ampliado el código, lo que hace que el comportamiento más claro:

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

salida de ejemplo extendido:

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

es increíble, pero eso es lo que php hace%) un error? – zerkms

+0

zerkms: me alegra que pueda confirmar el comportamiento. Después de usarlo por un tiempo, no creo que sea perfecto. Esta no es su fuerza principal. Pero tal vez podamos entender lo que sucede. OP karlthorwald - aka – user89021

+0

@karlthorwald: Esto es muy extraño, supongo que esto es un error de algún tipo. Intente enviarlo a través de PHP.net. –

Respuesta

4

Hay más información en this older question. La versión corta es que properties en objetos/clases de PHP siguen el mismo naming convention as variables. Una propiedad numérica no es válida en un objeto PHP, por lo que no existe una regla clara sobre lo que debería suceder al serializar un objeto desde otro idioma (json/javascript) que tenga una clave numérica. Si bien parece obvio para ti lo que debería suceder con lo anterior, alguien con un sesgo diferente ve el comportamiento de PHP en esta instancia como perfectamente válido y preferido.

Por lo tanto, es un tipo de error, pero más un área indefinida de la especificación sin una respuesta clara, por lo que no espere que el comportamiento cambie para satisfacer su gusto, y si cambia, no espere que cambio para ser permanente.

Para abordar algunos de los problemas en los comentarios, considere esto

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

que seria algo como esto

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

Una matriz con un cero clave única cadena no es un PHP válida construir. Si intentas crear un PHP, el cero se convertirá en int por ti. Cuando le pides a PHP que haga un cast para el cual no tiene una definición, termina creando una matriz con una clave de cadena (debido a las reglas mal definidas sobre lo que debería suceder aquí).

Si bien es descaradamente obvio que este comportamiento es "incorrecto" por parte de PHP, no es fácil definir el comportamiento correcto en un lenguaje débilmente tipado.

+0

Aún así, si 'print_r()' the '$ a' después de haber sido convertido como una matriz, puede ver claramente que el índice' 0' no se ha eliminado. –

+1

sí. acordado con @Alix. la explicación en http://stackoverflow.com/questions/1869812/casing-an-array-with-numeric-keys-as-an-object funciona para objetos. pero debido a que explicitamos el objeto a la matriz, esperamos que funcione de manera regular. incluso si una nueva matriz no contiene esa "clave mal formada", también se puede explicar (debido a la propiedad del objeto mal formada). pero la matriz semifuncional parece muy defectuosa. – zerkms

+1

Pregunta actualizada para abordar otros los comentarios. En el caso de $ a, está lanzando ** un objeto ya no válido ** como una matriz, por lo que ingresa un territorio de comportamiento indefinido y todas las apuestas están desactivadas. En el caso de $ b PHP arroja automáticamente el "0" como int para producir una matriz válida. Estoy de acuerdo en que es un comportamiento extraño, pero terminas con comportamientos raros similares en cualquier idioma que evita el tipado fuerte. –

1

Usted sólo puede acceder a ella como una objeto (stdClass) en lugar de una matriz:

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

Este es el más sencillo ya que su JavaScript era un objeto ({}) en lugar de una matriz [] para comenzar.

Alternativamente, usted puede hacer esto

$arr = json_decode($json, true); 

El segundo parámetro opcional

hace que la producción de una matriz asociativa. http://us.php.net/json_decode

+0

perdiste la tercera línea, donde el objeto se convirtió en una matriz. su respuesta no explica por qué podemos ver el artículo en var_dump() pero no podemos acceder a él. la pregunta general es acerca de la conversión 'object-> array' y no sobre cómo trabajar con' json_decode' – zerkms

+0

philfreo gracias. esto me ayuda a continuar con mi codificación. pero mantengo la pregunta abierta ahora y tal vez alguien explica el comportamiento inesperado que encontré. OP karlthorwald - aka – user89021

1

¿Por qué haces esto? ¿Sabes que puedes tener los valores decodificados JSON como una matriz directamente?

$arr = json_decode($json, true); 

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

Esto no justifica los resultados de todos modos ;-) ¿Lo hace? – zerkms

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

PHP inútil print_r ataca de nuevo!

La primera matriz tiene una clave entera 0, porque la conversión (array) intenta convertirla en una matriz plana tipo lista.

La segunda matriz conserva la clave de cadena de estilo de matriz asociativa '0' con la que la construyó.

Uso var_export en lugar de print_r y se puede ver la diferencia con mayor facilidad.

+0

'var_dump', en realidad – zerkms

+0

Ayuda mucho saber que print_r no funciona bien. Aún var_export muestra una clave de cadena (ver ejemplo extendido en la pregunta) – user89021

+0

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

1

Bueno, el problema solo existe cuando el objeto inicial tiene propiedades que no están permitidas [también conocidas como propiedades que son numéricas]. Esto no está relacionado con json_encode/decode, sino con cualquier operación que implique la conversión de objetos a una matriz. Todas las claves enteras se volverán inaccesibles.

http://www.php.net/manual/en/language.types.array.php - donde se señala que: Si un objeto se convierte en una matriz, el resultado es una matriz cuyos elementos son las propiedades del objeto. Las claves son los nombres de las variables miembro, con algunas excepciones notables: las propiedades enteras son inaccesibles; las variables privadas tienen el nombre de clase antepuesto al nombre de la variable; las variables protegidas tienen un '*' antepuesto al nombre de la variable. Estos valores antepuestos tienen bytes nulos en cualquier lado.