Skip to content

Commit

Permalink
Add tests and beginning functionality.
Browse files Browse the repository at this point in the history
  • Loading branch information
griffindy committed Feb 23, 2015
1 parent b812a70 commit 77c55f9
Showing 5 changed files with 112 additions and 2 deletions.
18 changes: 16 additions & 2 deletions lib/rackson.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
require "rackson/version"
require 'rackson/property'
require 'rackson/version'

module Rackson
# Your code goes here...
def self.included(base)
base.instance_variable_set(:@json_properties, [])
base.extend ClassMethods
end

module ClassMethods
def json_property(name, klass, options = {})
property = Rackson::Property.new(name, klass, options)
@json_properties << property
define_method(property.name) do
instance_variable_get("@#{property.name}")
end
end
end
end
42 changes: 42 additions & 0 deletions lib/rackson/object_mapper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
require 'json'

module Rackson
class ObjectMapper
def deserialize(string, klass)
hash = JSON.parse(string)
deserialize_from_hash(hash, klass)
end

def deserialize_from_hash(hash, klass)
klass.new.tap do |instance|
klass.instance_variable_get(:@json_properties).each do |property|
value = generate_value property, hash
instance.instance_variable_set("@#{property.name}", value)
end
end
end

private

def generate_value(property, json_hash)
value_from_json = json_hash.fetch(property.name.to_s) do |key|
if property.required?
raise "missing required key #{key}"
end
end

case value_from_json
# already cast to the appropriate class
when property.klass
value_from_json
# needs to be deserialized into its own object
when Hash
deserialize_from_hash(value_from_json, property.klass)
when NilClass
nil
else
raise "type mismatch between #{value_from_json.inspect} (a #{value_from_json.class}) and #{property.klass}"
end
end
end
end
15 changes: 15 additions & 0 deletions lib/rackson/property.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
module Rackson
class Property
attr_reader :name, :klass

def initialize(name, klass, options)
@name = name
@klass = klass
@options = options
end

def required?
!@options[:optional]
end
end
end
1 change: 1 addition & 0 deletions rackson.gemspec
Original file line number Diff line number Diff line change
@@ -20,4 +20,5 @@ Gem::Specification.new do |spec|

spec.add_development_dependency "bundler", "~> 1.7"
spec.add_development_dependency "rake", "~> 10.0"
spec.add_development_dependency "rspec", "~> 3.0"
end
38 changes: 38 additions & 0 deletions spec/rackson/object_mapper_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
require_relative '../../lib/rackson'
require_relative '../../lib/rackson/object_mapper'

describe Rackson::ObjectMapper do
let(:mapper) { Rackson::ObjectMapper.new }
class DifferentFakeObject
include Rackson
json_property :baz, String
end

class FakeObject
include Rackson
json_property :foo, String
json_property :bar, DifferentFakeObject
json_property :something_optional, String, optional: true
end

describe '#deserialize' do
let(:json_string) { '{"foo": "bar", "bar": {"baz":"another thing"}}' }
let(:deserialized) { mapper.deserialize(json_string, FakeObject) }

it 'returns an object of the given class' do
expect(deserialized).to be_a FakeObject
end

it 'sets the appropriate values' do
expect(deserialized.foo).to eq 'bar'
end

it 'understands non JSON POROs' do
expect(deserialized.bar.baz).to eq 'another thing'
end

it 'understands optional properties' do

end
end
end

0 comments on commit 77c55f9

Please sign in to comment.