Ruby on rails 提取可能是或可能不是数组的哈希键
我正在进行一个返回XML(JSON也可用)的API调用,响应体将显示错误(如果有)。可能只有一个或多个错误。当XML(或JSON)被解析为散列时,当存在多个错误时,保存错误的键将是一个数组,但当仅存在一个错误时,它将只是一个标准键。这使得解析变得很困难,因为我似乎无法找到一行同时适合这两种情况的代码 当出现一个错误时,对API的调用将返回此值Ruby on rails 提取可能是或可能不是数组的哈希键,ruby-on-rails,json,ruby,hash,Ruby On Rails,Json,Ruby,Hash,我正在进行一个返回XML(JSON也可用)的API调用,响应体将显示错误(如果有)。可能只有一个或多个错误。当XML(或JSON)被解析为散列时,当存在多个错误时,保存错误的键将是一个数组,但当仅存在一个错误时,它将只是一个标准键。这使得解析变得很困难,因为我似乎无法找到一行同时适合这两种情况的代码 当出现一个错误时,对API的调用将返回此值 <?xml version=\"1.0\" encoding=\"utf-8\"?><response><version&g
<?xml version=\"1.0\" encoding=\"utf-8\"?><response><version>1.0</version><code>6</code><message>Data validation failed</message><errors><error><parameter>rptFilterValue1</parameter><message>Parameter is too small</message></error></errors></response>
当出现多个错误时
<?xml version=\"1.0\" encoding=\"utf-8\"?><response><version>1.0</version><code>6</code><message>Data validation failed</message><errors><error><parameter>rptFilterValue1</parameter><message>Parameter is too small</message></error><error><parameter>rptFilterValue2</parameter><message>Missing required parameter</message></error></errors></response>
我使用以下方法将XML转换为哈希
Hash.from_xml(response.body).deep_symbolize_keys
这将返回以下哈希值
当只有一个错误时,哈希如下所示
{:response=>{:version=>"1.0", :code=>"6", :message=>"Data validation failed", :errors=>{:error=>{:parameter=>"rptFilterValue1", :message=>"Parameter is too small"}}}}
{:response=>{:version=>"1.0", :code=>"6", :message=>"Data validation failed", :errors=>{:error=>[{:parameter=>"rptFilterValue1", :message=>"Parameter is too small"}, {:parameter=>"rptFilterValue2", :message=>"Missing required parameter"}]}}}
data = Hash.from_xml(response.body).deep_symbolize_keys
if data[:response].has_key?(:errors)
errors = data[:response][:errors][:error].map{|x| "#{x.values[0]} #{x.values[1]}"}
当有2个错误时,哈希如下所示
{:response=>{:version=>"1.0", :code=>"6", :message=>"Data validation failed", :errors=>{:error=>{:parameter=>"rptFilterValue1", :message=>"Parameter is too small"}}}}
{:response=>{:version=>"1.0", :code=>"6", :message=>"Data validation failed", :errors=>{:error=>[{:parameter=>"rptFilterValue1", :message=>"Parameter is too small"}, {:parameter=>"rptFilterValue2", :message=>"Missing required parameter"}]}}}
data = Hash.from_xml(response.body).deep_symbolize_keys
if data[:response].has_key?(:errors)
errors = data[:response][:errors][:error].map{|x| "#{x.values[0]} #{x.values[1]}"}
当我第一次测试API响应时,我有多个错误,所以我获取错误消息的方式如下
{:response=>{:version=>"1.0", :code=>"6", :message=>"Data validation failed", :errors=>{:error=>{:parameter=>"rptFilterValue1", :message=>"Parameter is too small"}}}}
{:response=>{:version=>"1.0", :code=>"6", :message=>"Data validation failed", :errors=>{:error=>[{:parameter=>"rptFilterValue1", :message=>"Parameter is too small"}, {:parameter=>"rptFilterValue2", :message=>"Missing required parameter"}]}}}
data = Hash.from_xml(response.body).deep_symbolize_keys
if data[:response].has_key?(:errors)
errors = data[:response][:errors][:error].map{|x| "#{x.values[0]} #{x.values[1]}"}
但是,当只有一个错误时,代码会以参数的未定义方法“值”出错
我发现的唯一实际解决方法是测试错误键的类。当数组使用一种方法进行提取时,哈希使用另一种方法
if data[:response][:errors][:error].class == Array
errors = data[:response][:errors][:error].map{|x| "#{x.values[0]} #{x.values[1]}"}
else
errors = data[:response][:errors][:error].map{|x| "#{x[1]}"}
end
但我只是讨厌它。必须有一种方法从一个可能是数组也可能不是数组的键中提取xml/json数据。解决方案可能是从xml到哈希的转换,而不是在解析实际哈希时。我在网上找不到任何东西
我将感谢任何帮助或提示。如果您使用的是Rails,如果您可以执行,则可以使用。请先挖掘:
single = {:response=>{:version=>"1.0", :code=>"6", :message=>"Data validation failed", :errors=>{:error=>{:parameter=>"rptFilterValue1", :message=>"Parameter is too small"}}}}
Array.wrap(single.dig(:response, :errors, :error))
这将返回大小为1的数组:
[
{
:message => "Parameter is too small",
:parameter => "rptFilterValue1"
}
]
对于倍数:
multiple = {:response=>{:version=>"1.0", :code=>"6", :message=>"Data validation failed", :errors=>{:error=>[{:parameter=>"rptFilterValue1", :message=>"Parameter is too small"}, {:parameter=>"rptFilterValue2", :message=>"Missing required parameter"}]}}}
Array.wrap(multiple.dig(:response, :errors, :error))
这将返回大小为2的数组:
[
{
:message => "Parameter is too small",
:parameter => "rptFilterValue1"
},
{
:message => "Missing required parameter",
:parameter => "rptFilterValue2"
}
]
您可以使用Nokogiri
和xpath
解析XML,即使选择器指出单个元素,也会返回数组
errors=Nokogiri::XML(XML\u响应).xpath('//error')
errors.map{| e | e.children.each_with_object({}){| x,h | h[x.name]=x.content}
带有单个错误的API响应给出
=>[{“参数”=>“rptFilterValue1”,“消息”=>“参数太小”}]
和API结果,并出现多个错误
<?xml version=\"1.0\" encoding=\"utf-8\"?><response><version>1.0</version><code>6</code><message>Data validation failed</message><errors><error><parameter>rptFilterValue1</parameter><message>Parameter is too small</message></error><error><parameter>rptFilterValue2</parameter><message>Missing required parameter</message></error></errors></response>
=>[{“参数”=>“rptFilterValue1”,“消息”=>“参数太小”},{“参数”=>“rptFilterValue2”,“消息”=>“缺少所需参数”}]
如果没有错误
元素,您将得到一个空数组。旁注:使用对象#is_a?
而不是直接的类比较;后者对于所有派生类都会失败<代码>数据[:响应][:错误][:错误]。\u是?(数组)
(或者您可以将类与不等式进行比较:数据[:响应][:错误][:错误].class谢谢Jay。所以wrap方法使键成为数组…除非它已经是数组,否则它是有意义的!是的。它基本上与您所做的一样,但解决了一些边缘情况,并将其包装到公共类方法中。它的代码很短: