I've got a bit of a headache here - I'm pretty new to Ruby...
I've got a structure like so returned from Savon...
{
:item => [{
:key => "result",
:value=> "success"
},
{
:key => "data",
:value=> {
:item => [{ :key => "displayName",
:value => "Matt"
},
{
:key => "messages",
:value => {
:items => [{....}]
}
]
}
}]
}
And I need to get it to be like...
{
:result => success
:data => [{
:displayName => "Matt"
},
{
:messages => [{
:messageName => "Test Message"
}]
}]
}
So I can easily manipulate and navigate the data structure I've tried a few methods including just passing the value of :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
But this just gives me a tonne of Type errors for symbol to integer conversion (I assume that's the array index playing up). Any help much appreciated.
When trying to tackle problem like this in Ruby, it's useful to think of it in terms of transformations on your data. The Ruby Enumerable library is full of methods that help you manipulate regular data structures like Array and Hash.
A Ruby solution to this problem looks like:
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
Here's some sample input data and sample output:
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"}]}]}]
I think this version looks better, output-wise, but that's a call you'll have to make:
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"}}}
Note that the case
statement here is really the key, it allows you to quickly differentiate between different types of data you're converting, and the Hash[]
method converts key-value pairs into the Hash structure you're looking for.
This is similar to your attempt, but just passes through content it doesn't recognize as-is.
Savon provides a to_hash
method on the result. What I usually do is:
...
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];
... full script here https://gist.github.com/sroller/3d04842ab763f52b6623
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.