Как разобрать JSON с Ruby on Rails?

Я ищу простой способ разобрать JSON, извлечь значение и записать его в базу данных в Rails.

В частности, что я ищу, это способ извлечь shortUrl из JSON, возвращенного из bit.ly API:

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

И затем возьмите этот shortUrl и запишите его в объект ActiveRecord, связанный с длинным URL.

Это одна из тех вещей, которые я могу полностью мыслить в концепции, и когда я сажусь, чтобы исполнить, я понимаю, что мне есть чему поучиться.

Ответ 1

Эти ответы немного устарели. Поэтому я даю вам:

hash = JSON.parse string

Rails должна автоматически загружать модуль json для вас, поэтому вам не нужно добавлять require 'json'.

Ответ 2

Разбор JSON в Rails довольно прост:

parsed_json = ActiveSupport::JSON.decode(your_json_string)

Предположим, что объект, который вы хотите связать с shortUrl, - это объект сайта, который имеет два атрибута - short_url и long_url. Затем, чтобы получить shortUrl и связать его с соответствующим объектом сайта, вы можете сделать что-то вроде:

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

Ответ 3

Этот ответ довольно старый. pguardiario получил его.

Один сайт для проверки - реализация JSON для Ruby. Этот сайт предлагает драгоценный камень, который вы можете установить для более быстрого варианта расширения C.

С помощью тестов, приведенных на странице документации , они утверждают, что это 21.500x быстрее, чем ActiveSupport::JSON.decode

Код будет таким же, как ответ "Милан Новота" с этим камнем, но разбор будет просто:

parsed_json = JSON(your_json_string)

Ответ 4

Вот обновление для 2013 года.

рубин

Ruby 1.9 имеет по умолчанию JSON gem с расширениями C. Вы можете использовать его с помощью

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

Вариант parse! может использоваться для надежных источников. Есть и другие драгоценные камни, которые могут быть быстрее, чем реализация по умолчанию. Пожалуйста, обратитесь к multi_json для списка.

Рельсы

В современных версиях Rails используется multi_json, который автоматически использует самый быстрый JSON-камень. Таким образом, рекомендуется использовать

object = ActiveSupport::JSON.decode json_string

Подробнее см. ActiveSupport:: JSON. В частности, важная строка в источнике метода

data = MultiJson.load(json, options)

Затем в вашем Gemfile включите драгоценные камни, которые вы хотите использовать. Например,

group :production do
  gem 'oj'
end

Ответ 5

Ruby bundled JSON способен проявить немного магии самостоятельно.

Если у вас есть строка, содержащая сериализованные данные JSON, которые вы хотите проанализировать:

JSON[string_to_parse]

JSON будет смотреть на параметр, видеть его в String и попробовать декодировать его.

Аналогично, если у вас есть хэш или массив, который вы хотите сериализовать, используйте:

JSON[array_of_values]

Или:

JSON[hash_of_values]

И JSON будет сериализовать его. Вы также можете использовать метод to_json, если хотите избежать визуального сходства [].

Вот несколько примеров:

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

Если вы используете root в JSON, вы можете заметить его подмножество YAML, и на самом деле анализатор YAML - это то, что обрабатывает JSON. Вы также можете сделать это:

require 'yaml'

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

Если ваше приложение анализирует как YAML, так и JSON, вы можете позволить YAML обрабатывать оба варианта сериализованных данных.

Ответ 6

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

Это вернет хэш

Ответ 7

require 'json'

hash = JSON.parse string

работать с хешем и делать то, что вы хотите сделать.

Ответ 8

RUBY чувствителен к регистру.

require 'json' # json must be lower case

JSON.parse(<json object>)  

например

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

Ответ 9

Знак Oj (https://github.com/ohler55/oj) должен работать. Это просто и быстро.

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

Драгоценный камень Oj не будет работать для JRuby. Для JRuby это (https://github.com/ralfstx/minimal-json) или это (https://github.com/clojure/data.json) могут быть хорошими вариантами.

Ответ 10

В Ruby есть парсер JSON:

require 'json'

Ответ 11

Вот что я буду делать:

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]

Если вы знаете исходный URL-адрес, вы можете использовать:

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

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

Если вы не знаете ключ для исходного URL-адреса, вы можете сделать следующее:

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

Если вы не хотите искать ключи с помощью символов, вы можете преобразовать ключи в хэш в строки:

results = json[:results].stringify_keys

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

Если вы заинтересованы в изменении структуры JSON, вы можете создать простую схему JSON и проверить JSON перед попыткой доступа к ключам. Это обеспечит охрану.

ПРИМЕЧАНИЕ. Пришлось блокировать URL-адрес bit.ly из-за правил проводки.

Ответ 12

Вы можете попробовать что-то вроде этого:

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

 }.to_json
end