الأحد، 5 يناير 2014

Objectify Ruby Hashes from/to JSON API

I just released a ruby gem to use some JSON over HTTP API:

https://github.com/solyaris/blomming_api

My naif ruby code just convert complex/nested JSON data structures returned by API endpoints (json_data) to ruby Hashes ( hash_data), in a flat one-to-one transaltion (JSON to ruby hash and viceversa). Tat's fine, but...

I would like a programming interface more "high level". Maybe instatiating a class Resource for every endpoint, but I'm confused about a smart implementation.

Let me explain with an abstract code.

Let say I have a complex/nested JSON received by an API, usually an Array of Hashes, recursively nested as here below (imagination example):

json_data = '[{ "commute": { "minutes": 0, "startTime": "Wed May 06 22:14:12 EDT 2014", "locations": [ { "latitude": "40.4220061", "longitude": "40.4220061" }, { "latitude": "40.4989909", "longitude": "40.48989805" }, { "latitude": "40.4111169", "longitude": "40.42222869" } ] }},{ "commute": { "minutes": 2, "startTime": "Wed May 28 20:14:12 EDT 2014", "locations": [ { "latitude": "43.4220063", "longitude": "43.4220063" } ] }}]'

At the moment what I do, when I receive a similar JSON form an API is just:

# from JSON to hash hash_data = JSON.load json_data# and to assign values:coords = hash_data.first["commute"]["locations"].lastcoords["longitude"] = "40.00" # was "40.4111169"coords["latitude"] = "41.00" # was "40.42222869"

that's ok, but with awfull/confusing syntax. Instead, I probably would enjoy something like:

# create object Resource from hashres = Resource.create( hash_data )# ... some processing# assign a "nested" variables: longitude, latitude of object: rescoords = res.first.commute.locations.lastcoords.longitude = "40.00" # was "40.4111169"coords.latitude = "41.00" # was "40.42222869"# ... some processing# convert modified object: res into an hash again:modified_hash = res.save# and probably at least I'll recover to to JSON:modified_json = JSON.dump modified_hash

I read intresting posts: http://pullmonkey.com/2008/01/06/convert-a-ruby-hash-into-a-class-object/ http://www.goodercode.com/wp/convert-your-hash-keys-to-object-properties-in-ruby/

and copying Kerry Wilson' code, I sketched the implementation here below:

class Resource def self.create (hash) new ( hash) end def initialize ( hash) hash.to_obj end def save # or to_hash() # todo! HELP! (see later) endendclass ::Hash # add keys to hash def to_obj self.each do |k,v| v.to_obj if v.kind_of? Hash v.to_obj if v.kind_of? Array k=k.gsub(/\.|\s|-|\/|\'/, '_').downcase.to_sym ## create and initialize an instance variable for this key/value pair self.instance_variable_set("@#{k}", v) ## create the getter that returns the instance variable self.class.send(:define_method, k, proc{self.instance_variable_get("@#{k}")}) ## create the setter that sets the instance variable self.class.send(:define_method, "#{k}=", proc{|v| self.instance_variable_set("@#{k}", v)}) end return self endendclass ::Array def to_obj self.map { |v| v.to_obj } end end#------------------------------------------------------------

BTW, I studied a bit ActiveResource project (was part of Rails if I well understood). ARes could be great for my scope but the problem is ARes have a bit too "strict" presumption of full REST APIs... In my case server API are not completely RESTfull in the way ARes would expect... All in all I would do a lot of work to subclass / modify ARes behaviours and at the moment I discarded the idea to use ActiveResource

QUESTIONS:

someone could help me to realize the save() method on the above code (I'm really bad with recursive methods... :-( ) ?

Does exist some gem that to the above sketched hash_to_object() and object_to_hash() translation ?

What do you think about that "automatic" objectifying of an "arbitrary" hash coming froma JSON over http APIs ? I mean: I see the great pro that I do not need to client-side static-wire data structures, allowing to be flexible to possible server side variations. But on the other hand, doing this automatic objectify, there is a possible cons of a side effect to allow security issues ... like malicious JSON injection (possible untrasted communication net ...)

What do you think about all this ? Any suggestion is welcome! Sorry for my long post and my ruby language metaprogramming azards :-)

giorgio


View the original article here

ليست هناك تعليقات:

إرسال تعليق