自/至JSON API客体红宝石哈希(Objectify Ruby Hashes from/to J

2019-10-19 03:58发布

我刚刚发布了红宝石的宝石通过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

问题:

  1. 有人可以帮助我实现在上面的代码(我用递归方法非常糟糕...... :-()的save()方法?
  2. 确实存在一些的宝石,上面绘制的hash_to_object()和object_to_hash()的翻译?

  3. 你怎么看待“任意”散列未来弗罗马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

Answer 1:

此功能是通过几个宝石提供。 其中最知名的是Hashie ,特别是类Hashie::Mash

混搭是一个扩展的哈希值给出可通过哈希建成并易于扩展简单的伪对象的功能。 它的设计基于REST的API库被用来提供JSON和XML解析哈希容易喜欢对象的访问。

Mash还支持多级别的对象。



Answer 2:

根据您的需求和筑巢的水平,你可以逃脱的OpenStruct

我用一个简单的测试存根工作。 Hashie会工作得很好,但比我需要一个更大的工具(并添加依赖)。



文章来源: Objectify Ruby Hashes from/to JSON API