2011-07-26 9 views
9

Estoy tratando de escribir un script php que maneje datos de un servicio web que entregue "json" como una cadena. El problema es que la cadena no es realmente json; es javascript Específicamente, las claves no se citan, aunque sí las variables. Ejemplo (los datos reales es mucho más largo y más complicado):Manejo de JSON malformado en PHP

{desc:'User defined payload'} 

Como se describe por el php manual, json_decode() falla correctamente para interpretar esta cadena.

Mi pregunta es, ¿cómo puedo interpretar con éxito una cadena como esta en php?

La única solución que se me ocurre es escribir algunas expresiones regulares que corrijan la sintaxis, pero entonces tendría dos problemas.

EDITAR

sugerencia de utilizar el módulo Services_JSON pera de Hadvig trabajó, y se ve como una solución general. Una vez que tuve el módulo instalado, mi código se veía así:

require_once 'PEAR.php'; 
require_once 'Services/JSON.php'; 

$Services_JSON = new Services_JSON(); 
$data = $Services_JSON->decode($malformed_json); 

Desafortunadamente, esto es LENTO. ¡Interpretar toda la cadena (~ 400,000 caracteres) llevó> 36 segundos! Usar una expresión regular para arreglar las comillas y luego usar json_decode tomó ~ 0.04 segundos. Esto es lo que solía:

// fix single quotes 
$s = str_replace("'", '"', $malformed_json); 

// fix unquoted keys 
$valid_json = preg_replace('/([{\[,])\s*([a-zA-Z0-9_]+?):/', '$1"$2":', $s); 

$data = json_decode($valid_json); 

Por supuesto, esto se romperá si los datos contienen las comillas, paréntesis o comas.

+0

¿Podría modificar el proceso de creación de la cadena? –

+0

Si conoce la cita de dos problemas, entonces probablemente sepa la cita sobre el uso de expresiones regulares cuando debería usar un analizador;) – Dan

+0

PMV: desafortunadamente, no – Chris

Respuesta

1

Depende de la complejidad de los datos es:

$output = "{desc:'User defined payload',asc:'whatever'}"; 

function json_js_php($string){ 

    $string = str_replace("{",'{"',$string); 
    $string = str_replace(":'",'":"',$string); 
    $string = str_replace("',",'","',$string); 
    $string = str_replace("'}",'"}',$string); 
    return $string; 

} 

echo json_decode(json_js_php($output))->{'desc'}; 

devuelve: carga útil definida por el usuario

0

Si el problema es sólo los identificadores cotizados y los datos se puede suponer que no contiene ningún llaves, este debe hacerlo:

$goodJson = preg_replace("/{\s*([a-zA-Z0-9_]+)/", '{ "$1"', $badJson); 

(no probado!)

0

Prueba esto:

$jsonString = "{result:true,username:'usr000242',password:'123456',message:'Cannot send username and password to [email protected]'}"; 
function manualFixInvalidJSON($jsonString=''){ 
    $jsonString = preg_replace("/([{,])([a-zA-Z][^: ]+):/", "\$1\"$2\":", $jsonString); 
    $jsonString = preg_replace("/:([a-zA-Z\'][^:]+)([,}])/", ":\"$1\"$2", $jsonString); 
    $jsonString = json_decode($jsonString,true); 
    function trimer($val){ 
     return trim(trim($val,"'"),"\""); 
    } 
    $jsonString = array_map('trimer', $jsonString); 
    return json_encode($jsonString); 
} 
echo jsonString($jsonString); 
0

El uso de expresiones regulares es un no-go. La gramática JSON no se puede analizar correctamente utilizando regexp. Te abrirás a una tonelada de errores futuros.

Recomiendo usar algún tipo de analizador YAML. YAML es compatible con versiones anteriores de JSON y permite literales sin comillas al mismo tiempo.

Symfony YAML component funcionó muy bien para mí.

Y recuerde que habrá una penalización de rendimiento en comparación con json_decode porque se implementó de forma nativa.