我刚刚发布了红宝石的宝石通过HTTP API使用一些JSON:
https://github.com/solyaris/blomming_api
我纳伊夫红宝石代码只是转换由API端点(json_data)返回到红宝石散列(hash_data)络合物/嵌套JSON数据结构,在一个平面一到一个transaltion(JSON红宝石散列,反之亦然)。 TAT的罚款,但...
我想了一个编程接口更“高级”。 也许instatiating为每个端点一类资源,但我感到困惑的一个聪明的实现。
让我用一个抽象的代码解释。
让说,我有通过API获得了复杂/嵌套JSON,通常哈希的数组,递归嵌套这里下面(例如想象):
json_data = '[{
"commute": {
"minutes": 0,
"startTime": "Wed May 06 22:14:12 EDT 2014",
"locations": [
{
"latitude": "40.4220061",
"longitude": "40.4220061"
},
{
"latitude": "40.4989909",
"longitude": "40.48989805"
},
{
"latitude": "40.4111169",
"longitude": "40.42222869"
}
]
}
},
{
"commute": {
"minutes": 2,
"startTime": "Wed May 28 20:14:12 EDT 2014",
"locations": [
{
"latitude": "43.4220063",
"longitude": "43.4220063"
}
]
}
}]'
目前,我做什么,当我收到了类似的JSON形成API仅仅是:
# from JSON to hash
hash_data = JSON.load json_data
# and to assign values:
coords = hash_data.first["commute"]["locations"].last
coords["longitude"] = "40.00" # was "40.4111169"
coords["latitude"] = "41.00" # was "40.42222869"
这是确定的,但与awfull /混淆语法。 相反,我可能会喜欢的东西,如:
# create object Resource from hash
res = Resource.create( hash_data )
# ... some processing
# assign a "nested" variables: longitude, latitude of object: res
coords = res.first.commute.locations.last
coords.longitude = "40.00" # was "40.4111169"
coords.latitude = "41.00" # was "40.42222869"
# ... some processing
# convert modified object: res into an hash again:
modified_hash = res.save
# and probably at least I'll recover to to JSON:
modified_json = JSON.dump modified_hash
我读intresting帖子: http://pullmonkey.com/2008/01/06/convert-a-ruby-hash-into-a-class-object/ http://www.goodercode.com/wp/convert-your -hash密钥至对象的属性功能于红宝石/
并复制克里威尔逊的代码,我在这里勾勒下执行:
class Resource
def self.create (hash)
new ( hash)
end
def initialize ( hash)
hash.to_obj
end
def save
# or to_hash()
# todo! HELP! (see later)
end
end
class ::Hash
# add keys to hash
def to_obj
self.each do |k,v|
v.to_obj if v.kind_of? Hash
v.to_obj if v.kind_of? Array
k=k.gsub(/\.|\s|-|\/|\'/, '_').downcase.to_sym
## create and initialize an instance variable for this key/value pair
self.instance_variable_set("@#{k}", v)
## create the getter that returns the instance variable
self.class.send(:define_method, k, proc{self.instance_variable_get("@#{k}")})
## create the setter that sets the instance variable
self.class.send(:define_method, "#{k}=", proc{|v| self.instance_variable_set("@#{k}", v)})
end
return self
end
end
class ::Array
def to_obj
self.map { |v| v.to_obj }
end
end
#------------------------------------------------------------
顺便说一句,我研究了一下项目的ActiveResource(是的Rails的一部分,如果我理解了)。 ARES可以是伟大的我的范围,但问题是ARES有一点过于“严格”完全的REST API的假设......对我来说,服务器API不在方式战神完全的REST类型的期望......所有的一切我会做了很多工作来子/修改ARES行为,在现阶段,我丢弃了主意,用的ActiveResource
问题:
- 有人可以帮助我实现在上面的代码(我用递归方法非常糟糕...... :-()的save()方法?
确实存在一些的宝石,上面绘制的hash_to_object()和object_to_hash()的翻译?
你怎么看待“任意”散列未来弗罗马JSON通过HTTP API,它们“自动”客观化是什么? 我的意思是:我看到了伟大的职业,我不需要客户端的静态线的数据结构,允许灵活可能的服务器端的变化。 但在另一方面,这样做自动的客观化,存在的副作用可能的利弊,让安全问题......像恶意JSON注射(可能untrasted通信网...)
你怎么看待这一切呢? 任何的建议是欢迎! 对不起,我长的帖子,我的Ruby语言的元编程azards :-)
乔治
更新2:我还是对问题点兴趣阅读意见3:优点/缺点,以创建资源类每收到JSON优点/缺点创建静态(抢占属性)/ automatich /动态嵌套对象
更新1:长回复西蒙娜:谢谢,你是对的醪有一个甜美的.to_hash()方法:
require 'json'
require 'hashie'
json_data = '{
"commute": {
"minutes": 0,
"startTime": "Wed May 06 22:14:12 EDT 2014",
"locations": [
{
"latitude": "40.4220061",
"longitude": "40.4220061"
},
{
"latitude": "40.4989909",
"longitude": "40.48989805"
},
{
"latitude": "40.4111169",
"longitude": "40.42222869"
}
]
}
}'
# trasforma in hash
hash = JSON.load json_data
puts hash
res = Hashie::Mash.new hash
# assign a "nested" variables: longitude, latitude of object: res
coords = res.commute.locations.last
coords.longitude = "40.00" # was "40.4111169"
coords.latitude = "41.00" # was "40.42222869"
puts; puts "longitude: #{res.commute.locations.last.longitude}"
puts "latitude: #{res.commute.locations.last.latitude}"
modified_hash = res.to_hash
puts; puts modified_hash