web-dev-qa-db-fra.com

Comment analyser JSON avec Ruby sur Rails?

Je cherche un moyen simple d'analyser JSON, d'extraire une valeur et de l'écrire dans une base de données dans Rails.

Plus précisément, ce que je recherche, c’est un moyen d’extraire shortUrl du fichier JSON renvoyé par l’API bit.ly:

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

Et ensuite, prenez ce shortUrl et écrivez-le dans un objet ActiveRecord associé à l'URL longue.

C’est l’une de ces choses auxquelles je peux penser complètement dans le concept et quand je m’assieds pour exécuter, je me rends compte que j’ai beaucoup à apprendre.

308
Dan Sinker

Ces réponses sont un peu datées. Donc je te donne:

hash = JSON.parse string

Les rails doivent charger automatiquement le module json pour vous, de sorte que vous ne soyez pas devez ajouter require 'json'.

442
pguardiario

L'analyse de JSON dans Rails est assez simple:

parsed_json = ActiveSupport::JSON.decode(your_json_string)

Supposons que l'objet auquel vous souhaitez associer le shortUrl est un objet Site, qui possède deux attributs: short_url et long_url. Ensuite, pour obtenir le shortUrl et l’associer à l’objet Site approprié, vous pouvez faire quelque chose comme:

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

Cette réponse est assez ancienne. pguardiario l'a eu.

Un site à consulter est implémentation JSON pour Ruby . Ce site offre un bijou que vous pouvez installer pour une variante d’extension C beaucoup plus rapide.

Avec les repères étant donné leur page de documentation ils affirment qu'il est 21.500x plus rapide que ActiveSupport::JSON.decode

Le code serait le même que celui de Milan Novota avec cette gemme, mais l'analyse serait simplement:

parsed_json = JSON(your_json_string)
56
lillq

Voici une mise à jour pour 2013.

Ruby

Ruby 1.9 a une valeur par défaut gem JSON avec les extensions C. Vous pouvez l'utiliser avec

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

La variante parse! peut être utilisée pour des sources sûres . Il existe également d'autres joyaux, qui peuvent être plus rapides que l'implémentation par défaut. Veuillez vous référer à multi_json pour la liste.

Rails

Les versions modernes de Rails utilisent multi_json , une gemme qui utilise automatiquement la gemme JSON la plus rapide disponible. Ainsi, la méthode recommandée consiste à utiliser

object = ActiveSupport::JSON.decode json_string

Veuillez vous référer à ActiveSupport :: JSON pour plus d'informations. En particulier, la ligne importante dans la source de la méthode est

data = MultiJson.load(json, options)

Ensuite, dans votre Gemfile, incluez les gemmes que vous souhaitez utiliser. Par exemple,

group :production do
  gem 'oj'
end
19
James Lim

Le paquet de Ruby JSON est capable d’exhiber un peu de magie.

Si vous souhaitez analyser une chaîne contenant des données sérialisées JSON:

_JSON[string_to_parse]
_

JSON examinera le paramètre, verra que c'est une chaîne et essaiera de le décoder.

De même, si vous souhaitez sérialiser un tableau de hachage ou un tableau, utilisez:

_JSON[array_of_values]
_

Ou:

_JSON[hash_of_values]
_

Et JSON le sérialisera. Vous pouvez également utiliser la méthode to_json si vous souhaitez éviter la similarité visuelle de la méthode [] .

Voici quelques exemples:

_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}]
_

Si vous parcourez JSON, vous remarquerez peut-être qu'il s'agit d'un sous-ensemble de YAML. En réalité, l'analyseur YAML est ce qui gère JSON. Vous pouvez le faire aussi:

_require 'yaml'

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

Si votre application analyse à la fois YAML et JSON, vous pouvez laisser YAML gérer les deux types de données sérialisées.

7
the Tin Man
require 'json'
out=JSON.parse(input)

Cela retournera un hachage

5
user2726667
require 'json'

hash = JSON.parse string

travaillez avec le hash et faites ce que vous voulez faire.

5

Cela peut être fait comme ci-dessous, il suffit d’utiliser JSON.parse, vous pourrez ensuite le parcourir normalement avec des index.

#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"]
3
Nishant Rawat

Voici ce que je ferais:

json = "{\"errorCode\":0,\"errorMessage\":\"\",\"results\":{\"http://www.foo.com\":{\"hash\":\"e5TEd\",\"shortKeywordUrl\":\"\",\"shortUrl\":\"http://b.i.t.ly/1a0p8G\",\"userHash\":\"1a0p8G\"}},\"statusCode\":\"OK\"}"

hash = JSON.parse(json)
results = hash[:results]

Si vous connaissez l'URL source, vous pouvez utiliser:

source_url = "http://www.foo.com".to_sym

results.fetch(source_url)[:shortUrl]
=> "http://b.i.t.ly/1a0p8G"

Si vous ne connaissez pas la clé de l'URL source, vous pouvez procéder comme suit:

results.fetch(results.keys[0])[:shortUrl]
=> "http://b.i.t.ly/1a0p8G"

Si vous ne souhaitez pas rechercher les clés à l'aide de symboles, vous pouvez convertir les clés du hachage en chaînes:

results = json[:results].stringify_keys

results.fetch(results.keys[0])["shortUrl"]
=> "http://b.i.t.ly/1a0p8G"

Si vous pensez que la structure JSON pourrait changer, vous pouvez créer un schéma JSON simple et valider le JSON avant de tenter d'accéder aux clés. Cela fournirait une garde.

REMARQUE: il a fallu modifier l'URL bit.ly à cause des règles de publication.

2
Jurgen

Ruby est sensible à la casse.

require 'json' # json must be lower case

JSON.parse(<json object>)  

par exemple

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

La gemme Oj ( https://github.com/ohler55/oj ) devrait fonctionner. C'est simple et rapide.

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

Le joyau Oj ne fonctionnera pas pour JRuby. Pour JRuby, ceci ( https://github.com/ralfstx/minimal-json ) ou this ( https://github.com/clojure/data.json ) peut être de bonnes options.

2
John Moore