2012-02-20 9 views
16

Estoy usando net/http para extraer algunos datos json de la API de Yahoo Placemaker. Después de recibir la respuesta estoy realizando JSON.parse en la respuesta. Esto me da un hash que se parece a:No se puede usar la sintaxis de punto para hash de 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"=>""}}}} 

estoy en condiciones de acceder a los elementos haciendo cosas como jsonResponse['version'] pero no soy capaz de hacer jsonResponse.version. ¿Por qué es esto?

+0

No creo que Ruby apoye eso. –

Respuesta

42

Hash no tiene de sintaxis con punto de que es llaves. OpenStruct hace:

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

Solo para un nivel de puntos os.name.firstname no parece funcionar, os.name devuelve un hash normal – teknopaul

+0

Esto no funciona para hashes y arrays anidados. Ver la respuesta de whodabudda a continuación. –

5

Esa es una función de JavaScript, no una función de Ruby. En Ruby, para usar una "sintaxis de punto", el objeto debería responder a esos métodos. Los hashes de Ruby usan el método #[](key) para acceder a los elementos.

4

Por qué no, puede hacerlo a través de metaprogramming

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

Correcto, pero ¿para qué molestarse? – d11wtq

+1

+1: ¡eso es exactamente lo que haría! :) –

+0

interpolar cadena en comillas simples? :/Y usando 'stringify_keys!' Para normalizar las teclas primero. –

0

Debido Hash no tiene un método version.

8

La gema HashDot funcionaría para esto.

HashDot permite el uso de la sintaxis de notación de puntos en hash. También funciona en cadenas json que se han vuelto a analizar con 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

¡Bonita joya! ¡Gracias! – Richard

9

OpenStruct funciona bien para un hash puro, pero para los hashes con matrices Embebido u otros valores hash, la sintaxis con punto se ahogue. Me encontré con esta solución, que funciona bien sin carga en otra joya: https://coderwall.com/p/74rajw/convert-a-complex-nested-hash-to-an-object pasos básicos son:

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

ahora puede acceder a todos los objetos en mystr utilizando la sintaxis con punto.

+0

"Dado que tanto JSON como OpenStruct están en la Biblioteca estándar de Ruby, no tendremos dependencias de terceros". –

+0

Esta es la mejor respuesta y debe ser aceptada. –

Cuestiones relacionadas