0

Is it possible to have HTTParty deserialize the results from a GET to a strongly typed ruby object? For example

class Myclass
 include HTTParty

end

x = Myclass.get('http://api.stackoverflow.com/1.0/questions?tags=HTTParty')

puts x.total
puts x.questions[0].title

Right now it deserializes it into a hash

puts x["total"]

My question is actually if HTTParty supports this OTB, not by installing additional gems.

Edit:

I'm still new to Ruby, but I recall that class fields are all private so they would need to be accessed through getter/setter methods. So maybe this question isn't a valid one?

ILovePaperTowels
  • 1,445
  • 2
  • 17
  • 30
  • All you are going to get from a GET request is text. If that text represents a serialised ruby object, then you can unserialise it and get a ruby object. Is that what you are looking for? – Nerian Feb 09 '12 at 21:42
  • What comes back from the GET is json, but HTTParty deserializes it into a hash, but I would like the json to be deserialized into a strongly typed object. The keyword here is DESERIALIZE which I failed to put in the question. – ILovePaperTowels Feb 09 '12 at 21:51

2 Answers2

2

If you are just wanting method syntax, you can use an open struct.

require 'httparty'
require 'ostruct'

result = HTTParty.get 'http://api.stackoverflow.com/1.0/questions?tags=HTTParty'
object = OpenStruct.new result
object.total # => 2634237

A possible downside is that this object is totally open such that if you invoke a nonexistent method on it, it will just return nil (if you invoke a setter, it will create both the setter and getter)

Joshua Cheek
  • 30,436
  • 16
  • 74
  • 83
1

It sounds like you want the return value of Myclass::get to be an instance of Myclass. If that's the case, you could cache the return value from the HTTP request and implement method_missing to return values from that hash:

class Myclass
  include HTTParty

  attr_accessor :retrieved_values

  def method_missing(method, *args, &block)
    if retrieved_values.key?(method)
      retrieved_values[method]
    else
      super
    end
  end

  def self.get_with_massaging(url)
    new.tap do |instance|
      instance.retrieved_values = get_without_massaging(url)
    end
  end

  class << self
    alias_method :get_without_massaging, :get
    alias_method :get, :get_with_massaging
  end
end

This isn't exactly what you asked for, because it only works one level deep — i.e., x.questions[0].title would need to be x.questions[0][:title]

x = Myclass.get('http://api.stackoverflow.com/1.0/questions?tags=HTTParty')
p x.total
p x.questions[0][:title]

Perhaps you could come up with some hybrid of this answer and Joshua Creek's to take advantage of OpenStruct.

I should also point out that all the method aliasing trickery isn't necessary if your method doesn't have to be named get.

Brandan
  • 14,735
  • 3
  • 56
  • 71