2012-02-20 20 views
16

Używam net/http do pobierania niektórych danych json z interfejsu API Yahoo Placemaker. Po otrzymaniu odpowiedzi wykonuję JSON.parse w odpowiedzi. To daje mi hash, który wygląda tak:Nie można użyć składni kropkowej dla mieszania ruby ​​

{"processingTime"=>"0.001493", "version"=>"1.4.0.526 build 111113", "documentLength"=>"25", "document"=>{"administrativeScope"=>{"woeId"=>"2503863", "type"=>"Town", "name"=>"Tampa, FL, US", "centroid"=>{"latitude"=>"27.9465", "longitude"=>"-82.4593"}}, "geographicScope"=>{"woeId"=>"2503863", "type"=>"Town", "name"=>"Tampa, FL, US", "centroid"=>{"latitude"=>"27.9465", "longitude"=>"-82.4593"}}, "localScopes"=>{"localScope"=>{"woeId"=>"2503863", "type"=>"Town", "name"=>"Tampa, FL, US (Town)", "centroid"=>{"latitude"=>"27.9465", "longitude"=>"-82.4593"}, "southWest"=>{"latitude"=>"27.8132", "longitude"=>"-82.6489"}, "northEast"=>{"latitude"=>"28.1714", "longitude"=>"-82.2539"}, "ancestors"=>[{"ancestor"=>{"woeId"=>"12587831", "type"=>"County", "name"=>"Hillsborough"}}, {"ancestor"=>{"woeId"=>"2347568", "type"=>"State", "name"=>"Florida"}}, {"ancestor"=>{"woeId"=>"23424977", "type"=>"Country", "name"=>"United States"}}]}}, "extents"=>{"center"=>{"latitude"=>"27.9465", "longitude"=>"-82.4593"}, "southWest"=>{"latitude"=>"27.8132", "longitude"=>"-82.6489"}, "northEast"=>{"latitude"=>"28.1714", "longitude"=>"-82.2539"}}, "placeDetails"=>{"placeId"=>"1", "place"=>{"woeId"=>"2503863", "type"=>"Town", "name"=>"Tampa, FL, US", "centroid"=>{"latitude"=>"27.9465", "longitude"=>"-82.4593"}}, "placeReferenceIds"=>"1", "matchType"=>"0", "weight"=>"1", "confidence"=>"8"}, "referenceList"=>{"reference"=>{"woeIds"=>"2503863", "placeReferenceId"=>"1", "placeIds"=>"1", "start"=>"15", "end"=>"20", "isPlaintextMarker"=>"1", "text"=>"Tampa", "type"=>"plaintext", "xpath"=>""}}}} 

jestem w stanie uzyskać dostęp do elementów wykonując takie rzeczy jak jsonResponse['version'] ale nie jestem w stanie zrobić jsonResponse.version. Dlaczego to?

+0

Nie sądzę, że Ruby to obsługuje. –

Odpowiedz

42

Hash nie posiada składnię dot-to klucze. OpenStruct robi:

require 'ostruct' 
hash = {:name => 'John'} 
os = OpenStruct.new(hash) 
p os.name #=> "John" 
+0

Tylko dla jednego poziomu punktów nazwa os.name.first nie działa, nazwa os.nazwraca normalny hasz – teknopaul

+0

Nie działa dla zagnieżdżonych skrótów i tablic. Zobacz odpowiedź whodabudda poniżej. –

5

To jest funkcja JavaScript, a nie funkcja Ruby. W Ruby, aby użyć "składni punktowej", obiekt musiałby odpowiedzieć na te metody. W hasłach Ruby można uzyskać dostęp do elementów za pomocą metody #[](key).

4

Czemu nie, można to zrobić za pośrednictwem metaprogramowanie

module LookLikeJSON 
    def method_missing(meth, *args, &block) 
    if has_key?(meth.to_s) 
     self[meth.to_s] 
    else 
     raise NoMethodError, 'undefined method #{meth} for #{self}' 
    end 
    end 
end 

h = {"processingTime"=>"0.001493", "version"=>"1.4.0.526 build 111113", "documentLength"=>"25"} 
h.extend(LookLikeJSON) 
h.processingTime #=> "0.001493" 
+2

Dobrze, ale po co zawracać sobie głowę? – d11wtq

+1

+1: dokładnie to zrobię! :) –

+0

ciąg interpolacji w jednym cudzysłowie? :/I używając 'stringify_keys!', Aby najpierw normalizować klucze. –

0

Ponieważ Hash nie ma metody version.

8

Klejnot o wartości HashDot byłby odpowiedni do tego.

HashDot pozwala na stosowanie składni notacji kropek na hasłach. Działa również na ciągach json, które zostały ponownie przeanalizowane pod numerem JSON.parse.

require 'hash_dot' 

hash = {b: {c: {d: 1}}}.to_dot 
hash.b.c.d => 1 

json_hash = JSON.parse(hash.to_json) 
json_hash.b.c.d => 1 
+0

Niezły klejnot! Dzięki! – Richard

9

OpenStruct będzie działać dobrze dla czystego hash, ale dla mieszań z tablic osadzone lub innych skrótów, składnia kropka dusić. Natknąłem się na to rozwiązanie, które działa dobrze bez załadunku w innym gem: https://coderwall.com/p/74rajw/convert-a-complex-nested-hash-to-an-object podstawowe etapy to:

data = YAML::load(File.open("your yaml file")) 
json_data = data.to_json 
mystr = JSON.parse(json_data,object_class: OpenStruct) 

można uzyskać dostęp do wszystkich obiektów w mystr używając składni kropka.

+0

"Ponieważ zarówno JSON, jak i OpenStruct znajdują się w Rubinowej Bibliotece Standardowej, nie będziemy mieć żadnych zależności od innych firm." –

+0

To jest najlepsza odpowiedź i należy ją zaakceptować. –

Powiązane problemy