Cómo recorrer un objeto PHP con claves dinámicas [duplicate]

9 minutos de lectura

Avatar de usuario de John Doe
Juan Pérez

Traté de analizar un archivo JSON usando PHP. Pero estoy atascado ahora.

Este es el contenido de mi archivo JSON:

{
    "John": {
        "status":"Wait"
    },
    "Jennifer": {
        "status":"Active"
    },
    "James": {
        "status":"Active",
        "age":56,
        "count":10,
        "progress":0.0029857,
        "bad":0
    }
}

Y esto es lo que he probado hasta ahora:

<?php

$string = file_get_contents("/home/michael/test.json");
$json_a = json_decode($string, true);

echo $json_a['John'][status];
echo $json_a['Jennifer'][status];

Pero como no sé los nombres (como 'John', 'Jennifer') y todas las claves y valores disponibles (como 'age', 'count') de antemano, creo que necesito crear un bucle foreach.

Agradecería un ejemplo de esto.

  • Estás en el camino correcto. Busque la sintaxis de foreach (debe obtener claves y valores). ¡No te rindas todavía!

    – Stefan Mai

    3 de diciembre de 2010 a las 8:12

  • @Stefan Mai: foreach($variable as $key => $val) debería ser lo que quieres 🙂

    – Bojangles

    3 de diciembre de 2010 a las 8:15

  • Nota al margen: le sugiero que configure su configuración de PHP para mostrar todo tipo de mensajes de error, incluidos notices

    –Álvaro González

    3 de diciembre de 2010 a las 8:39

  • ¿Puede dar más detalles sobre lo que está tratando de obtener al “analizar” el JSON: es decir, qué tarea está tratando de lograr con su código (como: “salir todos los estados”, “buscar nombres donde el estado es xyz”, “buscar toda la información para xyz”)?

    – Salathe

    3 de diciembre de 2010 a las 10:43

  • X-Ref: ¿Cómo extraigo datos de JSON con PHP? (para una transversión de matriz más meticulosa).

    – mario

    4 de febrero de 2018 a las 11:12

Avatar de usuario de Gordon
gordon

Para iterar sobre una matriz multidimensional, puede usar RecursiveArrayIteratorRecursiveArrayIterator

$jsonIterator = new RecursiveIteratorIterator(
    new RecursiveArrayIterator(json_decode($json, TRUE)),
    RecursiveIteratorIterator::SELF_FIRST);

foreach ($jsonIterator as $key => $val) {
    if(is_array($val)) {
        echo "$key:\n";
    } else {
        echo "$key => $val\n";
    }
}

Producción:

John:
status => Wait
Jennifer:
status => Active
James:
status => Active
age => 56
count => 10
progress => 0.0029857
bad => 0

ejecutar en el teclado

  • ¿Este enfoque ofrece alguna ventaja especial sobre el viejo foreach?

    –Álvaro González

    3 de diciembre de 2010 a las 8:32

  • @Álvaro obviamente. Con foreach solo puedes recurrir a un nivel de profundidad. Con el enfoque anterior, puede recurrir a una matriz de varios niveles. Además, todo está encapsulado en OOP, por lo que tiene una mejor reutilización y puede simularlo fácilmente en UnitTests, además puede apilar iteradores con otros iteradores que hacen cosas diferentes, como limitar, almacenar en caché, filtrar, etc. además de cualquier iteradores personalizados que quizás desee crear.

    – Gordon

    3 de diciembre de 2010 a las 8:39


  • bien, no había considerado que el nivel de anidamiento fuera variable. En tal caso, esto es más limpio que una función recursiva.

    –Álvaro González

    3 de diciembre de 2010 a las 9:04

  • Sin embargo, este análisis de estilo deja cierta ambigüedad. Por ejemplo {'John':{'status':'waiting', 'Mary':{'status','nested'}}, 'Suzy':{'status:'waiting'} } es indistinguible de {'John':{'status':'waiting'}, 'Mary':{'status','nested'}, 'Suzy':{'status:'waiting'} }. Eso Mary es un hijo estructural de John está perdido.

    – Jesse Chisholm

    29 de agosto de 2015 a las 23:51

  • @Jesse php.net/manual/en/class.recursiveiteratoriterator.php le permitiría detectar la profundidad.

    – Gordon

    30 de agosto de 2015 a las 7:08

Avatar de usuario de BoltClock
PernoReloj

No puedo creer que tanta gente esté publicando respuestas sin leer el JSON correctamente.

Si itera foreach $json_a solo, tienes un objeto de objetos. Incluso si pasas true como segundo parámetro, tiene una matriz bidimensional. Si está recorriendo la primera dimensión, no puede repetir la segunda dimensión así. Así que esto está mal:

foreach ($json_a as $k => $v) {
   echo $k, ' : ', $v;
}

Para hacer eco de los estados de cada persona, intente esto:

<?php

$string = file_get_contents("/home/michael/test.json");
if ($string === false) {
    // deal with error...
}

$json_a = json_decode($string, true);
if ($json_a === null) {
    // deal with error...
}

foreach ($json_a as $person_name => $person_a) {
    echo $person_a['status'];
}

?>

  • Si los archivos php y json están en el mismo directorio, podemos leer json con file_get_contents("test.json"); (No es necesario poner la ruta).

    – eQ19

    16 de abril de 2015 a las 9:55


  • @Chetabahana Eso en realidad no es correcto. Si usa una ruta relativa como test.json, entonces la ruta se evalúa en relación con el directorio actual, no necesariamente donde se encuentra el script PHP. En bash, puede descubrir el directorio actual escribiendo pwd.

    – Flamm

    28 de agosto de 2019 a las 13:22

  • @Flimm Si PHP y JSON y la ejecución ocurren en el mismo directorio, no es necesario especificar la ruta absoluta del archivo JSON. ¿Correcto?

    – Nguai al

    21 de enero de 2021 a las 4:33

  • @Nguaial Eso depende de cuál sea el directorio de trabajo actual. Por ejemplo, supongamos que tiene un archivo PHP /home/user/project/test.php y un archivo JSON /home/user/project/json.json. Si su trabajo actual es /home/userluego, para ejecutar el archivo PHP, escribiría php project/test.php. En este caso, el archivo PHP debería hacer referencia al archivo JSON como project/test.json ya que las rutas relativas son relativas al directorio de trabajo actual, no necesariamente al directorio principal del archivo PHP.

    – Flamm

    22 de enero de 2021 a las 14:11

avatar de usuario de swift
rápido

La solución más elegante:

$shipments = json_decode(file_get_contents("shipments.js"), true);
print_r($shipments);

Recuerde que el archivo json debe estar codificado en UTF-8 sin BOM. Si el archivo tiene BOM, json_decode devolverá NULL.

Alternativamente:

$shipments = json_encode(json_decode(file_get_contents("shipments.js"), true));
echo $shipments;

  • Bastante impresionante, pero todo el asunto de la Lista de materiales (BOM) me tiene totalmente confundido. emm… de que estas hablando? ¿Soy el único chico molesto por el uso de abreviaturas misteriosas e inexplicables? Está bien usar abreviaturas, pero explique cuándo se usó por primera vez (WFU)… gracias.

    – zipzit

    12 de febrero de 2015 a las 1:26

  • BOM = marca de orden de bytes.

    – veloz

    2 de marzo de 2015 a las 9:35

  • en.wikipedia.org/wiki/Byte_order_mark Gotcha típico si está trabajando con json tanto en Mac como en PC, ya que usan diferentes formatos de texto predeterminados.

    – veloz

    2 de marzo de 2015 a las 9:41

  • Esta publicación no intenta responder la pregunta publicada.

    – mickmackusa

    28 de marzo de 2019 a las 12:02

Avatar de usuario de Thariama
thariama

Intentar

<?php
$string = file_get_contents("/home/michael/test.json");
$json_a = json_decode($string,true);

foreach ($json_a as $key => $value){
  echo  $key . ':' . $value;
}
?>

Avatar de usuario de David
David

Me supera por completo que nadie haya señalado que sus “etiquetas” iniciales son incorrectas. Está creando un objeto con {}, mientras que podría crear una matriz con [].

[ // <-- Note that I changed this
    {
        "name" : "john", // And moved the name here.
        "status":"Wait"
    },
    {
        "name" : "Jennifer",
        "status":"Active"
    },
    {
        "name" : "James",
        "status":"Active",
        "age":56,
        "count":10,
        "progress":0.0029857,
        "bad":0
    }
] // <-- And this.

Con este cambio, el json se analizará como una matriz en lugar de un objeto. Y con esa matriz, puedes hacer lo que quieras, como bucles, etc.

  • Tienes razón al señalar lo de la matriz.

    – Stephen Adelakun

    23 de agosto de 2016 a las 8:40


  • Ay mía Debo agregar que parece que ha eliminado la clave en el json del OP al convertirlo en una matriz. Entonces el OP tiene razón.

    – Stephen Adelakun

    23 de agosto de 2016 a las 8:51

  • “Pero porque no sé los nombres (como John, Jennifer) y todas las claves disponibles”. Parece no conocer las claves, por lo que la única forma de recorrer la colección es un bucle. Este tipo de me dice que no dirige el acceso a los valores por clave.

    – David

    24/08/2016 a las 19:25

  • Esta publicación no responde a la pregunta de cómo analizar una cadena json y acceder a elementos de subarreglo desde claves desconocidas de primer nivel. Esto no es una respuesta y debe ser un comentario debajo de la pregunta. Casi parece que está recomendando que el archivo se lea y luego se transforme mediante funciones de cadena para adaptarse a sus preferencias. no lo entiendo

    – mickmackusa

    28 de marzo de 2019 a las 11:26


  • No, estoy señalando que la estructura del archivo es incorrecta para el propósito que está leyendo. Y por lo tanto responde a la pregunta. Y de hecho parece que no lo entiendes, porque no dije nada sobre las funciones de cadena. Eso es una tontería.

    – David

    2 de abril de 2019 a las 11:26

Avatar de usuario de Dane Brouwer
Dane Brouwer

Prueba esto

    $json_data="{
    "John": {
        "status":"Wait"
    },
    "Jennifer": {
        "status":"Active"
    },
    "James": {
        "status":"Active",
        "age":56,
        "count":10,
        "progress":0.0029857,
        "bad":0
      }
     }";

    $decode_data = json_decode($json_data);
    foreach($decode_data as $key=>$value){

            print_r($value);
    }

  • Tienes razón al señalar lo de la matriz.

    – Stephen Adelakun

    23 de agosto de 2016 a las 8:40


  • Ay mía Debo agregar que parece que ha eliminado la clave en el json del OP al convertirlo en una matriz. Entonces el OP tiene razón.

    – Stephen Adelakun

    23 de agosto de 2016 a las 8:51

  • “Pero porque no sé los nombres (como John, Jennifer) y todas las claves disponibles”. Parece no conocer las claves, por lo que la única forma de recorrer la colección es un bucle. Este tipo de me dice que no dirige el acceso a los valores por clave.

    – David

    24/08/2016 a las 19:25

  • Esta publicación no responde a la pregunta de cómo analizar una cadena json y acceder a elementos de subarreglo desde claves desconocidas de primer nivel. Esto no es una respuesta y debe ser un comentario debajo de la pregunta. Casi parece que está recomendando que el archivo se lea y luego se transforme mediante funciones de cadena para adaptarse a sus preferencias. no lo entiendo

    – mickmackusa

    28 de marzo de 2019 a las 11:26


  • No, estoy señalando que la estructura del archivo es incorrecta para el propósito que está leyendo. Y por lo tanto responde a la pregunta. Y de hecho parece que no lo entiendes, porque no dije nada sobre las funciones de cadena. Eso es una tontería.

    – David

    2 de abril de 2019 a las 11:26

Intentar:

$string = file_get_contents("/home/michael/test.json");
$json = json_decode($string, true);

foreach ($json as $key => $value) {
    if (!is_array($value)) {
        echo $key . '=>' . $value . '<br />';
    } else {
        foreach ($value as $key => $val) {
            echo $key . '=>' . $val . '<br />';
        }
    }
}

  • Prueba esto Las respuestas tienen poco valor en StackOverflow porque hacen muy poco para educar al OP y a los futuros investigadores. Si va a dejar esta respuesta en la página, explique cómo funciona su respuesta y por qué es recomendable.

    – mickmackusa

    1 de septiembre de 2018 a las 3:46

¿Ha sido útil esta solución?