2012-02-20 43 views
16

我使用net/http從雅虎Placemaker API中提取一些json數據。收到回覆後,我正在對回覆執行JSON.parse。這給了我一個哈希看起來像:無法使用紅點散列的點語法

{"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"=>""}}}} 

我能夠做的事情一樣jsonResponse['version']訪問元素,但我不能做jsonResponse.version。爲什麼是這樣?

+0

我不認爲Ruby支持。 – 2012-02-20 05:58:18

回答

42

Hash做到這一點沒有點語法爲它的鍵。 OpenStruct作用:

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

只有一個級別的點os.name.firstname似乎不起作用,os.name返回一個正常的散列 – teknopaul 2016-12-14 12:47:07

+0

這不適用於嵌套散列和數組。請參閱下面的whodabudda的答案。 – 2017-12-25 14:36:33

5

這是一個JavaScript功能,而不是Ruby功能。在Ruby中,要使用「點語法」,對象需要響應這些方法。 Ruby哈希使用#[](key)方法來訪問元素。

4

爲什麼不呢,你可以通過元編程

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

對,但爲什麼要麻煩? – d11wtq 2012-02-20 07:15:10

+1

+1:這正是我要做的! :) – 2012-02-20 07:26:16

+0

在單引號內插字符串? :/使用'stringify_keys!'來首先標準化鍵。 – 2012-03-06 04:49:19

0

因爲Hash沒有version方法。

8

HashDot寶石會爲此工作。

HashDot允許在散列上使用點表示法語法。它也適用於已被重新分析爲JSON.parse的json字符串。

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

好的寶石!謝謝! – Richard 2017-08-02 15:37:45

9

OpenStruct將工作做好的純哈希,但對於嵌入式陣列或其他哈希散列,點語法就會窒息。我碰到這個解決方案,這在另一顆寶石效果很好,無負載: https://coderwall.com/p/74rajw/convert-a-complex-nested-hash-to-an-object 基本步驟是:

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

您現在可以訪問使用點語法在myStr中的所有對象。

+0

「由於JSON和OpenStruct都位於Ruby標準庫中,因此我們不會有第三方依賴項。」 – 2017-12-03 14:38:06

+0

這是最好的答案,應該被接受。 – 2017-12-25 14:35:37