将 ruby 结构转换为散列

Converting a ruby structure to a hash

我有点头疼 - 我是 Ruby 的新手...

我有一个从 Savon 返回的类似结构...

{
  :item => [{
              :key =>  "result",
              :value=> "success"
            },
            {
              :key =>  "data",
              :value=> {
                  :item => [{ :key => "displayName", 
                              :value => "Matt" 
                            },
                            {
                              :key => "messages",
                              :value => { 
                                  :items => [{....}]
                            }
                       ]
               }
       }]
}

我需要让它像...

{
  :result => success
  :data => [{
              :displayName => "Matt"
           },
           {
              :messages => [{
                              :messageName => "Test Message"
                           }]
           }]
}

所以我可以轻松地操作和导航数据结构 我尝试了一些方法,包括只传递 :item 的值 ...

def convertData(data)
  result = {}
  if(data!=nil)
    data.each do |item|
      key = item[:key] 
      value = item[:value] 
      if(value.instance_of?(Hash))
        result[key] = convertData(value[:item])
      else
        result[key] = value
      end  
    end
  end
  return result
end

但这只会给我大量的符号到整数转换的类型错误(我假设这是数组索引正在播放)。非常感谢任何帮助。

在尝试解决 Ruby 中的此类问题时,根据数据的 转换 来考虑它会很有用。 Ruby Enumerable 库中充满了可帮助您操作常规数据结构(如 Array 和 Hash)的方法。

此问题的 Ruby 解决方案如下所示:

def desavon(data)
  case (data)
  when Hash
    if (data[:item])
      data[:item].collect do |item|
        { item[:key] => desavon(item[:value]) }
      end
    else
      # raise error?
    end
  else
    data
  end
end

下面是一些示例输入数据和示例输出:

input = {
  item: [
    {
      key: "result",
      value: "success"
    },
    {
      key:  "data",
      value: {
        item: [
          {
            key: "displayName", 
            value: "Matt" 
          },
          {
            key: "messages",
            value: { 
              item: [
                {
                  key: 'messageName',
                  value: 'Test Message'
                }
              ]
            }
          }
        ]
      }
    }
  ]
}

desavon(input)
# => [{"result"=>"success"}, {"data"=>[{"displayName"=>"Matt"}, {"messages"=>[{"messageName"=>"Test Message"}]}]}]

我认为这个版本在输出方面看起来更好,但这是你必须做出的决定:

def desavon(data)
  case (data)
  when Hash
    if (data[:item])
      Hash[
        data[:item].collect do |item|
          [ item[:key], desavon(item[:value]) ]
        end
      ]
    else
      # raise error?
    end
  else
    data
  end
end

desavon(input)
# => {"result"=>"success", "data"=>{"displayName"=>"Matt", "messages"=>{"messageName"=>"Test Message"}}}

注意这里的case语句才是真正的关键,它可以让你快速区分你正在转换的不同类型的数据,而Hash[]方法将键值对转换为您要查找的哈希结构。

这与您的尝试类似,但只是通过它无法按原样识别的内容。

Savon 对结果提供了 to_hash 方法。 我通常做的是:

...

response = @client.request :wsdl, :conversion_rate do
  soap.body = {
    "FromCurrency" => from_curr,
    "ToCurrency" => to_curr
  }
end    
response.to_hash[:conversion_rate_response][:conversion_rate_result];

... 完整脚本在这里 https://gist.github.com/sroller/3d04842ab763f52b6623