2011-01-27 29 views
10

Necesito convertir un archivo CSV a JSON en el servidor usando PHP. Estoy usando este script que funciona:CSV a JSON con PHP?

function csvToJSON($csv) { 
    $rows = explode("\n", $csv); 

    $i = 0; 
    $len = count($rows); 
    $json = "{\n" . ' "data" : ['; 
    foreach ($rows as $row) { 
     $cols = explode(',', $row); 
     $json .= "\n  {\n"; 
     $json .= '   "var0" : "' . $cols[0] . "\",\n"; 
     $json .= '   "var1" : "' . $cols[1] . "\",\n"; 
     $json .= '   "var2" : "' . $cols[2] . "\",\n"; 
     $json .= '   "var3" : "' . $cols[3] . "\",\n"; 
     $json .= '   "var4" : "' . $cols[4] . "\",\n"; 
     $json .= '   "var5" : "' . $cols[5] . "\",\n"; 
     $json .= '   "var6" : "' . $cols[6] . "\",\n"; 
     $json .= '   "var7" : "' . $cols[7] . "\",\n"; 
     $json .= '   "var8" : "' . $cols[8] . "\",\n"; 
     $json .= '   "var9" : "' . $cols[9] . "\",\n"; 
     $json .= '   "var10" : "' . $cols[10] . '"'; 
     $json .= "\n  }"; 

     if ($i !== $len - 1) { 
      $json .= ','; 
     } 

     $i++; 
    } 
    $json .= "\n ]\n}"; 

    return $json; 
} 

$json = csvToJSON($csv); 
$json = preg_replace('/[ \n]/', '', $json); 

header('Content-Type: text/plain'); 
header('Cache-Control: no-cache'); 
echo $json; 

La variable $csv es una cadena que resulta de una solicitud cURL que devuelve el contenido de CSV.

Estoy seguro de que este no es el código PHP más eficiente para hacerlo porque soy un desarrollador principiante y mi conocimiento de PHP es bajo. ¿Existe una manera mejor y más eficiente de convertir CSV a JSON utilizando PHP?

Gracias de antemano.

Nota. Soy consciente de que estoy agregando espacio en blanco y luego lo eliminé, lo hago así que puedo tener la opción de devolver JSON "legible" quitando la línea $json = preg_replace('/[ \n]/', '', $json); con fines de prueba.

Editar. Gracias por sus respuestas, basadas en ellos el nuevo código es así:

function csvToJson($csv) { 
    $rows = explode("\n", trim($csv)); 
    $csvarr = array_map(function ($row) { 
     $keys = array('var0','var1','var2','var3','var4','var5','var6','var7','var8','var9','var10'); 
     return array_combine($keys, str_getcsv($row)); 
    }, $rows); 
    $json = json_encode($csvarr); 

    return $json; 
} 

$json = csvToJson($csv); 

header('Content-Type: application/json'); 
header('Cache-Control: no-cache'); 
echo $json; 

Respuesta

23

Bueno, existe la función json_encode(), que debe utilizar en lugar de construir la salida JSON usted mismo. Y también hay un str_getcsv función() para analizar CSV:

$array = array_map("str_getcsv", explode("\n", $csv)); 
print json_encode($array); 

Sin embargo, debe adaptar el $ array si desea que la salida JSON para mantener los campos nombrados.

+1

Muchas gracias, este es un muy limpia solución, edité mi publicación con el código que estoy usando ahora en función de su respuesta más agregué array_combine para dar salida a JSON con nombres de propiedad. – VerizonW

+0

@VerizonW: Usar el cierre también es un truco muy bueno. – mario

+0

+1 Eso me gusta. No sabía sobre 'str_getcsv'. Si también sabe cómo evitar la ruptura de celdas multilínea ...: D – kaiser

1

Algunos consejos ...

  • Si tiene habilitada la apertura de URL para fopen() y envoltorios, puede utilizar fgetscsv().
  • Puede crear una matriz de CSV y luego convertirla con PHP nativo json_encode().
  • El tipo de mime correcto para JSON es application/json.
+0

gracias, ahora estoy usando json_encode() y corregido el tipo MIME. – VerizonW

0

Probablemente podría reducir la sobrecarga eliminando todos los espacios y \ n's. Pero eso está en tu nota.

Puede aumentar el rendimiento omitiendo preg_replace y pasando un booleano que lo activaría y desactivaría.

Aparte de eso, el desenrollamiento variable de tu var [1-10] en realidad es bueno, siempre y cuando siempre haya diez varaibles.

El enfoque explosivo y el foreach están bien.

+0

acabé quitando los espacios utilizando una solución mucho más limpio ahora, gracias. – VerizonW

0

Recomiendo usar Coseva (una biblioteca de análisis csv) y usar el método integrado enJSON().

<?php 

// load 
require('../src/CSV.php'); 

// read 
$csv = new Coseva\CSV('path/to/my_csv.csv'); 

// parse 
$csv->parse(); 

// disco 
echo $csv->toJSON(); 
6

Modifiqué la respuesta en la pregunta para usar la primera línea del CSV para las teclas del conjunto. Esto tiene la ventaja de no tener que codificar las claves en la función, lo que le permite trabajar con cualquier CSV con encabezados de columna y cualquier cantidad de columnas.

aquí está mi versión modificada:

function csvToJson($csv) { 
    $rows = explode("\n", trim($csv)); 
    $data = array_slice($rows, 1); 
    $keys = array_fill(0, count($data), $rows[0]); 
    $json = array_map(function ($row, $key) { 
     return array_combine(str_getcsv($key), str_getcsv($row)); 
    }, $data, $keys); 

    return json_encode($json); 
} 
0

Ninguna de estas respuestas trabajar con células de varias líneas, ya que todos ellos asumen una fila termina con '\ n'. La función integrada fgetcsv comprende que las celdas de línea múltiple están encerradas en "para que no se encuentre con el mismo problema. El código siguiente en lugar de confiar en '\ n' para encontrar cada fila de un csv permite que fgetcsv vaya fila por fila y prepare nuestro salida.

function csv_to_json($file){ 

    $columns = fgetcsv($file); // first lets get the keys. 
    $output = array(); // we will build out an array of arrays here. 

    while(!feof($file)){ // until we get to the end of file, we'll pull in a new line 
     $line = fgetcsv($file); // gets the next line 
     $lineObject = array(); // we build out each line with our $columns keys 
     foreach($columns as $key => $value){ 
      $lineObject[$value] = $line[$key]; 
     } 
     array_push($output, $lineObject); 
    } 
    return json_encode($output); // encode it as json before sending it back 
}