2011-02-03 10 views
9

Ho bisogno di analizzare alcuni JSON non validi in Ruby.Come analizzare JSON non valido con chiavi non quotate utilizzando ActiveSupport 3 (Rails)

Qualcosa di simile:

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

Come si può vedere, è invalido perché la chiave hash non è citato, dovrebbe essere

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

Ma questo non può essere cambiato e devo analizzare le chiavi non quotate.

Potrei analizzarlo con ActiveSupport 2.x, ma ActiveSupport 3 non mi consente. Mi butta:

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

Tra l'altro, si tratta di un'applicazione di Ruby utilizzando alcune librerie Rails, ma non è un'applicazione Rails

Grazie in anticipo

+0

Da dove proviene questo json non valido? A riposo o qualche file? Sarebbe meglio riparare effettivamente JSON, un parser che accetta json non valido è cattivo e sono contento che stiano usando Yajl ora. –

+0

Sì, è un'API. E sì, puzza che devo fare una soluzione per questo, ma non ho alcun contatto con gli sviluppatori dell'API. –

risposta

0

qualcosa di simile?

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

Wow ho pensato che avrei potuto risolvere il problema senza pre-analisi del JSON (magari attivando una sorta di flag di ActiveSupport). Vado a dare un'occhiata più da vicino a quel codice e ti faccio sapere come funziona per me. –

+0

mi dispiace, mi ha generato un'eccezione SyntaxError: 'espressione regolare non valida; non esiste uno schema precedente, in cui '{' definirà la cardinalità su 1:/{|: "/' –

2

vorrei usare un'espressione regolare per risolvere questo JSON non valida:

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

Ecco un'espressione regolare in qualche modo robusto è possibile utilizzare. Non è perfetto - in particolare non funziona in alcuni casi angolo in cui i valori stessi contengono testo JSON-like, ma funzionerà nei casi più generali:

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

In primo luogo sembra sia per un { o , quali sono le opzioni per il carattere che precede il nome di una chiave (consente anche qualsiasi quantità di spazio bianco con \s*). Cattura questo come un gruppo:

([{,]\s*) 

Poi si coglie la chiave stessa, che è composto di lettere, cifre e underscore (che regex comodamente fornisce una classe di \w carattere per):

(\w+) 

Infine, corrisponde a ciò che deve seguire un nome chiave; cioè, due punti seguiti da una citazione iniziale (per un valore stringa) o una cifra (per un valore numerico). Permette anche spazi in più, e cattura il tutto in un gruppo:

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

Per ogni partita, mette solo i tre pezzi di nuovo insieme, ma con le virgolette intorno alla chiave (così virgolette intorno cattura gruppo # 2):

'\1"\2"\3' 
Problemi correlati