【发布时间】:2019-12-03 21:25:22
【问题描述】:
我正在进行一个返回 XML(JSON 也可用)的 API 调用,并且响应正文将显示错误(如果有)。可能只有一个错误或多个错误。当 XML(或 JSON)被解析为散列时,当存在多个错误时,保存错误的键将是一个数组,但当仅存在一个错误时,它将只是一个标准键。这使得解析变得困难,因为我似乎无法想出适合这两种情况的一行代码
当出现一个错误时,对 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></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"}}}}
当有 2 个错误时,哈希是这样的
{: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"}]}}}
当我第一次测试 API 响应时,我遇到了多个错误,所以我获取错误消息的方式是这样的
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]}"}
但是,当只有一个错误时,代码会因参数未定义的方法“值”而出错
我发现的唯一实际解决方法是测试错误键的类。当 Array 我使用一种方法进行提取时,当 Hash 我使用另一种方法时。
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 到哈希的转换中,而不是在解析实际哈希时。我在网上找不到任何东西。
我将不胜感激任何帮助或提示。
【问题讨论】:
-
旁注:使用
Object#is_a?代替直接类比较;后者对于所有派生类都将失败。data[:response][:errors][:error].is_a?(Array)(或者你可以比较不等式的类:data[:response][:errors][:error].class <= Array。
标签: ruby-on-rails json ruby hash