Come analizzare JSON con Ruby on Rails?

Sto cercando un modo semplice per analizzare JSON, estrarre un valore e scriverlo in un database in Rails.

In particolare quello che sto cercando, è un modo per estrarre shortUrl dal JSON restituito dall’API bit.ly:

 { "errorCode": 0, "errorMessage": "", "results": { "http://www.foo.com": { "hash": "e5TEd", "shortKeywordUrl": "", "shortUrl": "http://bit.ly/1a0p8G", "userHash": "1a0p8G" } }, "statusCode": "OK" } 

E poi prendi quella shortUrl e scrivila in un object ActiveRecord associato all’URL lungo.

Questa è una di quelle cose che posso pensare interamente nel concetto e quando mi siedo per eseguire mi rendo conto che ho molto da imparare.

Queste risposte sono un po ‘datate. Perciò ti do:

 hash = JSON.parse string 

Rails dovrebbe caricare automaticamente il modulo json per te, quindi non è necessario aggiungere require 'json' .

L’analisi di JSON in Rails è abbastanza semplice:

 parsed_json = ActiveSupport::JSON.decode(your_json_string) 

Supponiamo che l’object a cui si desidera associare shortUrl sia un object Site, che ha due attributi: short_url e long_url. Quindi, per ottenere lo shortUrl e associarlo all’object Site appropriato, puoi fare qualcosa come:

 parsed_json["results"].each do |longUrl, convertedUrl| site = Site.find_by_long_url(longUrl) site.short_url = convertedUrl["shortUrl"] site.save end 

Questa risposta è abbastanza vecchia. pguardiario ce l’ha.

Un sito da verificare è l’ implementazione JSON per Ruby . Questo sito offre una gem che puoi installare per una variante di estensione C molto più veloce.

Con i benchmark forniti alla loro pagina di documentazione , affermano che è 21.500 volte più veloce di ActiveSupport::JSON.decode

Il codice sarebbe lo stesso della risposta di Milan Novota con questa gem, ma l’analisi sarebbe solo:

 parsed_json = JSON(your_json_string) 

Ecco un aggiornamento per il 2013.

Rubino

Ruby 1.9 ha una gem JSON predefinita con estensioni C. Puoi usarlo con

 require 'json' JSON.parse ''{ "x": "y" }' # => {"x"=>"y"} 

Il parse! la variante può essere utilizzata per fonti sicure . Ci sono anche altre gemme, che potrebbero essere più veloci dell’implementazione predefinita. Si prega di fare riferimento a multi_json per la lista.

Rails

Le versioni moderne di Rails utilizzano multi_json , una gem che utilizza automaticamente la gem JSON più veloce disponibile. Quindi, il modo consigliato è quello di utilizzare

 object = ActiveSupport::JSON.decode json_string 

Per ulteriori informazioni, consultare ActiveSupport :: JSON . In particolare, la linea importante nella fonte del metodo è

 data = MultiJson.load(json, options) 

Poi nel tuo Gemfile, includi le gemme che vuoi usare. Per esempio,

 group :production do gem 'oj' end 

Il JSON in bundle di Ruby è in grado di esibire un po ‘di magia da solo.

Se si dispone di una stringa contenente dati serializzati JSON che si desidera analizzare:

 JSON[string_to_parse] 

JSON guarderà il parametro, vedrà che è una stringa e prova a decodificarlo.

Allo stesso modo, se hai un hash o array che vuoi serializzato, usa:

 JSON[array_of_values] 

O:

 JSON[hash_of_values] 

E JSON lo serializzerà. Puoi anche usare il metodo to_json se vuoi evitare la somiglianza visiva del metodo [] .

Ecco alcuni esempi:

 hash_of_values = {'foo' => 1, 'bar' => 2} array_of_values = [hash_of_values] JSON[hash_of_values] # => "{\"foo\":1,\"bar\":2}" JSON[array_of_values] # => "[{\"foo\":1,\"bar\":2}]" string_to_parse = array_of_values.to_json JSON[string_to_parse] # => [{"foo"=>1, "bar"=>2}] 

Se si esegue il root in JSON, si potrebbe notare che si tratta di un sottoinsieme di YAML e, in realtà, il parser YAML è ciò che sta gestendo JSON. Puoi farlo anche tu:

 require 'yaml' YAML.load(string_to_parse) # => [{"foo"=>1, "bar"=>2}] 

Se la tua app sta analizzando sia YAML che JSON, puoi consentire a YAML di gestire entrambi i tipi di dati serializzati.

 require 'json' out=JSON.parse(input) 

Ciò restituirà un hash

 require 'json' hash = JSON.parse string 

lavora con l’hash e fai quello che vuoi fare.

La gem Oj ( https://github.com/ohler55/oj ) dovrebbe funzionare. È semplice e veloce.

http://www.ohler.com/oj/#Simple_JSON_Writing_and_Parsing_Example

 require 'oj' h = { 'one' => 1, 'array' => [ true, false ] } json = Oj.dump(h) # json = # { # "one":1, # "array":[ # true, # false # ] # } h2 = Oj.load(json) puts "Same? #{h == h2}" # true 

La gem Oj non funzionerà per JRuby. Per JRuby questo ( https://github.com/ralfstx/minimal-json ) o questo ( https://github.com/clojure/data.json ) possono essere buone opzioni.

RUBY è case sensitive.

 require 'json' # json must be lower case JSON.parse() 

per esempio

 JSON.parse(response.body) # JSON must be all upper-case 

Ecco cosa farei:

 json = "{\"errorCode\":0,\"errorMessage\":\"\",\"results\":{\"http://www.foo.com\":{\"hash\":\"e5TEd\",\"shortKeywordUrl\":\"\",\"shortUrl\":\"http://bitly/1a0p8G\",\"userHash\":\"1a0p8G\"}},\"statusCode\":\"OK\"}" hash = JSON.parse(json) results = hash[:results] 

Se conosci l’url di origine, puoi utilizzare:

 source_url = "http://www.foo.com".to_sym results.fetch(source_url)[:shortUrl] => "http://bitly/1a0p8G" 

Se non conosci la chiave per l’url di origine, puoi fare quanto segue:

 results.fetch(results.keys[0])[:shortUrl] => "http://bitly/1a0p8G" 

Se non vuoi cercare le chiavi usando i simboli, puoi convertire le chiavi dell’hash in stringhe:

 results = json[:results].stringify_keys results.fetch(results.keys[0])["shortUrl"] => "http://bitly/1a0p8G" 

Se sei preoccupato che la struttura JSON possa cambiare, potresti creare un semplice schema JSON e convalidare il JSON prima di tentare di accedere alle chiavi. Questo fornirebbe una guardia.

NOTA: è stato necessario manipolare l’URL bit.ly a causa delle regole di pubblicazione.

Questo può essere fatto come di seguito, basta usare JSON.parse , quindi puoi attraversarlo normalmente con gli indici.

 #ideally not really needed, but in case if JSON.parse is not identifiable in your module require 'json' #Assuming data from bitly api is stored in json_data here json_data = '{ "errorCode": 0, "errorMessage": "", "results": { "http://www.foo.com": { "hash": "e5TEd", "shortKeywordUrl": "", "shortUrl": "http://whateverurl", "userHash": "1a0p8G" } }, "statusCode": "OK" }' final_data = JSON.parse(json_data) puts final_data["results"]["http://www.foo.com"]["shortUrl"] 

Ruby ha un parser JSON:

 require 'json' 

Puoi provare qualcosa come questo:

 def details_to_json { :id => self.id, :credit_period_type => self.credit_period_type, :credit_payment_period => self.credit_payment_period, }.to_json end