Ruby - попытка перебрать хеш с вложенным хешем (после десериализации объекта JSON) - PullRequest
2 голосов
/ 05 октября 2019

Я совершенно новичок в Ruby, и я подумал, что напишу программу, которая будет вызывать API и десерилизировать объект JSON.

Для справки, вот API, который я вызываю;https://api.exchangeratesapi.io/latest?base=GBP

У меня проблемы с итерацией по хешу, я получаю следующую ошибку:

Traceback (most recent call last):
        2: from ruby-api.rb:21:in `<main>'
        1: from ruby-api.rb:21:in `each'
ruby-api.rb:23:in `block in <main>': undefined method `each' for "GBP":String (NoMethodError)

Вот код, который у меня есть (с комментариями)

#requiring the library for http client
require 'net/http'
#require the URI library
require 'uri'
#requiring the json library for deserialising JSON objects
require 'json'

#output of get request stored in a string to deserialise JSON
json_string = Net::HTTP.get(URI.parse('https://api.exchangeratesapi.io/latest?base=GBP'))

#testing output
puts "Direct output \n#{json_string}"

puts "First JSON Parse attempt\n"
JSON.parse(json_string).each do |currency, rate|
    puts "#{currency} - #{rate}"
end

#parse the JSON object to a hash and iterate through it, displaying each key, value pair
puts "JSON Parse output with nested each statements \n"
JSON.parse(json_string).each do |key, value|
    #however - this contains a nested hash! So a nested each do is needed.
    value.each do |currency, rate|
        puts "#{currency} - #{rate}"
    end
end

Вот полный вывод для того, когда я запускаю код:

Direct output
{"rates":{"CAD":1.6409680499,"HKD":9.6691560447,"ISK":152.3948565332,"PHP":63.800325678,"DKK":8.3851984951,"HUF":373.6986916727,"CZK":28.9078555786,"GBP":1.0,"RON":5.3321354371,"SEK":12.1404907631,"IDR":17442.1809197597,"INR":87.4181593576,"BRL":5.0228536133,"RUB":79.8944353978,"HRK":8.3345499467,"JPY":131.652535235,"THB":37.5506766242,"CHF":1.2255601101,"EUR":1.1230276826,"MYR":5.16064911,"BGN":2.1964175417,"TRY":7.0194845303,"CNY":8.8154304004,"NOK":11.220731091,"NZD":1.9484530294,"ZAR":18.6923465663,"USD":1.2329720928,"MXN":24.1548655174,"SGD":1.7001516087,"AUD":1.824583076,"ILS":4.2960300971,"KRW":1473.7716884721,"PLN":4.8565332135},"base":"GBP","date":"2019-10-04"}
First JSON Parse attempt
rates - {"CAD"=>1.6409680499, "HKD"=>9.6691560447, "ISK"=>152.3948565332, "PHP"=>63.800325678, "DKK"=>8.3851984951, "HUF"=>373.6986916727, "CZK"=>28.9078555786, "GBP"=>1.0, "RON"=>5.3321354371, "SEK"=>12.1404907631, "IDR"=>17442.1809197597, "INR"=>87.4181593576, "BRL"=>5.0228536133, "RUB"=>79.8944353978, "HRK"=>8.3345499467, "JPY"=>131.652535235, "THB"=>37.5506766242, "CHF"=>1.2255601101, "EUR"=>1.1230276826, "MYR"=>5.16064911, "BGN"=>2.1964175417, "TRY"=>7.0194845303, "CNY"=>8.8154304004, "NOK"=>11.220731091, "NZD"=>1.9484530294, "ZAR"=>18.6923465663, "USD"=>1.2329720928, "MXN"=>24.1548655174, "SGD"=>1.7001516087, "AUD"=>1.824583076, "ILS"=>4.2960300971, "KRW"=>1473.7716884721, "PLN"=>4.8565332135}
base - GBP
date - 2019-10-04
JSON Parse output with nested each statements
CAD - 1.6409680499
HKD - 9.6691560447
ISK - 152.3948565332
PHP - 63.800325678
DKK - 8.3851984951
HUF - 373.6986916727
CZK - 28.9078555786
GBP - 1.0
RON - 5.3321354371
SEK - 12.1404907631
IDR - 17442.1809197597
INR - 87.4181593576
BRL - 5.0228536133
RUB - 79.8944353978
HRK - 8.3345499467
JPY - 131.652535235
THB - 37.5506766242
CHF - 1.2255601101
EUR - 1.1230276826
MYR - 5.16064911
BGN - 2.1964175417
TRY - 7.0194845303
CNY - 8.8154304004
NOK - 11.220731091
NZD - 1.9484530294
ZAR - 18.6923465663
USD - 1.2329720928
MXN - 24.1548655174
SGD - 1.7001516087
AUD - 1.824583076
ILS - 4.2960300971
KRW - 1473.7716884721
PLN - 4.8565332135
Traceback (most recent call last):
        2: from ruby-api.rb:21:in `<main>'
        1: from ruby-api.rb:21:in `each'
ruby-api.rb:23:in `block in <main>': undefined method `each' for "GBP":String (NoMethodError)

Так что происходит то, что он будет счастливо перебирать хеш, но как только он нажмет клавишу «base» (со значением GBP) - оно падает.

Какой лучший способ решить эту проблему? Спасибо!

1 Ответ

2 голосов
/ 05 октября 2019

Вы пытаетесь перебрать каждое значение в проанализированном JSON, который работает в то же время, потому что значение rates является хешем, а значения для base и date являются строками. Там вы вызываете each и получаете исключение NoMethodError.

Попробуйте вместо этого получить доступ к клавише dates:

JSON.parse(json_string)['rates'].each do |currency, rate|
  puts "#{currency} - #{rate}"
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...