繁体   English   中英

如何在哈希参数中重命名符号?

[英]How to rename a symbol in hash parameters?

我有来自外部API的参数,这些参数使用我想适合我的Rails应用的CamelCase格式化JSON响应:

{"AccountID"=>"REAWLLY_LONG_HASH_API_KEY_FROM_EXTERNAL_SERVICE", 
"ChannelProductDescription"=>"0004", "Currency"=>"CAD", 
"CurrentBalance"=> {"Amount"=>"162563.64", "Currency"=>"CAD"}}

使用以下脚本,我将它们转换为小写:

data = JSON.parse(response, symbolize_keys: true)
data = {:_json => data} unless data.is_a?(Hash)
data.deep_transform_keys!(&:underscore)
data.deep_symbolize_keys!

让我这样正确格式化params

{:account_id=>"REAWLLY_LONG_HASH_API_KEY_FROM_EXTERNAL_SERVICE", 
:channel_product_description=>"SAVINGS", :currency=>"CAD", 
:current_balance=> {:amount=>"43.00", :currency=>"CAD"}}

我正在尝试将此外部API响应映射到通用的Rails模型Account ,该API调用中的JSON将作为参数干净地返回到我的数据库中,以允许一个干净的保存接口,例如:

@account = Account.create(ParamParser.call(params))

但是我遇到了转换:account_id的问题,因为该参数与数据库的主键冲突。

为了解决这个问题,我的想法是将params[:account_id]所有符号实例转换为params[:account_key_id] ,以使这些参数不会与我的数据库现有的account_id字段冲突。

我该怎么做?有没有比这里描述的更好的方法来使用外部JSON API?

Hash#deep_transform_keys这样做:

返回具有由块操作转换的所有键的新哈希。 这包括来自根哈希以及所有嵌套哈希和数组的键。

因此,您可以使用适当的代码块一口气完成此操作,例如:

data.deep_transform_keys! do |key|
  key = key.underscore.to_sym
  key = :account_key_id if(key == :account_id)
  key
end

您也可以将symbolize_keys: true标志也放到JSON.parse ,无论如何您都在更改所有键,所以不要打扰。

如果您经常做这种事情,那么您可以编写一个方法,该方法采用键映射哈希,并为您提供用于转换键的lambda:

def key_mangler(key_map = { })
  ->(key) do
    key = key.underscore.to_sym
    key = key_map[key] if(key_map.has_key?(key))
    key
  end
end

然后说像这样的话:

data.deep_transform_keys!(&key_mangler(:account_id => :account_key_id))

您可能想要使用与key_mangler不同的名称,但是该名称足以说明这个想法。


顺便说一句,如果您要将此JSON发送到数据库中,那么您可能不必费心使用符号键,JSON仅将字符串用于键,因此您将仅将字符串转换为符号,以便将它们转换回字符串。 当然,如果在从数据库中提取JSON时要对键进行符号化,则可能需要保持一致并全面使用符号。

除了先前的答案...

不幸的是,据我所知,在Hash上没有一种方法可以一次完成此操作。 我一直都是用蛮力实现的,例如:

hash[:new_key] = hash[:old_key]
hash.delete(:old_key)

在下面的注释中,“ mu is too short”建议的快捷方式是:

hash[:new_key] = hash.delete(:old_key)

在irb中进行说明:

2.4.1 :002 > h = { foo: :bar }
 => {:foo=>:bar}
2.4.1 :003 > h[:foo_new] = h.delete(:foo)
 => :bar
2.4.1 :004 > h
 => {:foo_new=>:bar}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM