2011-02-03 7 views
9

Necesito analizar ciertos JSON no válidos en Ruby.Cómo analizar el JSON no válido con las teclas sin usar el uso de ActiveSupport 3 (Rails)

Algo así como:

json_str = '{name:"Javier"}' 
ActiveSupport::JSON.decode json_str 

Como se puede ver, es válida porque la tecla de almohadilla no es citado, debe ser

json_str = '{"name":"Javier"}' 

Pero eso no puede ser cambiado y tengo que analizar las claves sin comillas.

Podría analizarlo con ActiveSupport 2.x, pero ActiveSupport 3 no me lo permite. Me lanza:

Yajl::ParseError: lexical error: invalid string in json text. 
             {name:"Javier"} 
        (right here) ------^ 

Por cierto, es una aplicación de Ruby usando algunas bibliotecas Rails, pero no es una aplicación Rails

Gracias de antemano

+0

¿De dónde viene este inválido json? ¿Una api de descanso o algún archivo? Sería mejor arreglar el json, un analizador que acepta el json no válido es malo y me alegro de que ahora usen Yajl. –

+0

Sí, es una API. Y sí apesta que tengo que hacer una solución para esto, pero no tengo ningún contacto con los desarrolladores de la API. –

Respuesta

0

Algo como esto?

require 'json' 
json_str = '{name:"Javier"}' 
hash = JSON::parse(json_str.gsub(/{|:"/, {'{'=>'{"', ':"'=>'":"'})) 
+0

Wow, pensé que podría arreglar eso sin pre-analizar el JSON (tal vez activando algún tipo de indicador de ActiveSupport). Voy a ver más de cerca ese código y te haré saber cómo funciona para mí. –

+0

lo siento, me provocó una excepción SyntaxError: 'expresión regular no válida; no hay un patrón anterior, al cual '{' definiría la cardinalidad en 1:/{|: "/' –

2

me gustaría utilizar una expresión regular para solucionar este JSON válido:

json_str = '{name:"Javier"}' 
json_str.gsub!(/(['"])?([a-zA-Z0-9_]+)(['"])?:/, '"\2":') 
hash = Yajl::Parser.parse(json_str) 
0

Aquí es una expresión regular un poco robusta que puede utilizar. No es perfecto - en concreto que no funciona en algunos casos extremos, donde los valores en sí contienen texto JSON-como, pero funcionará en los casos más generales:

quoted_json = unquoted_json.gsub(/([{,]\s*)(\w+)(\s*:\s*["\d])/, '\1"\2"\3') 

En primer lugar se ve ya sea para un { o , cuáles son las opciones para el carácter que precede a un nombre de tecla (también permite cualquier cantidad de espacio en blanco con \s*). Captura esto como un grupo:

([{,]\s*) 

Entonces Captura la propia llave, que está compuesto de letras, dígitos y guiones bajos (que RegEx convenientemente suministra una clase \w caracteres para):

(\w+) 

Finalmente, coincide con lo que debe seguir un nombre clave; es decir, dos puntos seguidos por una comilla de inicio (para un valor de cadena) o un dígito (para un valor numérico). También permite espacios en blanco extra, y capta todo el asunto en un grupo:

(\s*:\s*["\d]) 

Para cada partido, que sólo pone las tres piezas juntas, pero con comillas alrededor de la tecla (por lo comillas grupo de captura # 2):

'\1"\2"\3' 
Cuestiones relacionadas