json_mapper 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +3 -0
- data/Gemfile +10 -0
- data/LICENSE +20 -0
- data/README.rdoc +95 -0
- data/Rakefile +33 -0
- data/VERSION +1 -0
- data/init.rb +2 -0
- data/json_mapper.gemspec +71 -0
- data/lib/json_mapper.rb +144 -0
- data/lib/json_mapper/attribute.rb +40 -0
- data/lib/json_mapper/attribute_list.rb +20 -0
- data/test.rb +28 -0
- data/test/fixtures/complex.json +21 -0
- data/test/fixtures/simple.json +5 -0
- data/test/json_mapper_test.rb +104 -0
- data/test/support/models.rb +21 -0
- data/test/test_helper.rb +20 -0
- metadata +150 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Trond Arve Nordheim
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
= JSON Mapper
|
2
|
+
by Trond Arve Nordheim -
|
3
|
+
{Binary Marbles}[http://www.binarymarbles.com/]
|
4
|
+
|
5
|
+
== NOTICE
|
6
|
+
|
7
|
+
This is a project under heavy development. The API is far from stable yet, and
|
8
|
+
the code is very unclean in some places. The API won't be considered stable
|
9
|
+
until full tests are available verifying that all functionality is working as
|
10
|
+
expected.
|
11
|
+
|
12
|
+
== Description
|
13
|
+
|
14
|
+
A Ruby gem for mapping data from JSON data structures into Ruby class representations.
|
15
|
+
|
16
|
+
== Features
|
17
|
+
|
18
|
+
* Simple one to one mappings
|
19
|
+
* Complex mappings (many to one)
|
20
|
+
* Associations
|
21
|
+
* Type checking
|
22
|
+
|
23
|
+
== Usage
|
24
|
+
|
25
|
+
=== Simple one to one mapping
|
26
|
+
class Model
|
27
|
+
|
28
|
+
include JSONMapper
|
29
|
+
|
30
|
+
# Map the "id" attribute from the JSON data structure to the id attribute of the class,
|
31
|
+
# using Integer as the data type
|
32
|
+
json_attribute :id, Integer
|
33
|
+
|
34
|
+
# Map the "model_title" attribute from the JSON data structure to the title attribute of
|
35
|
+
# the class, using String as the data type
|
36
|
+
json_attribute :title, :model_title, String
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
=== Complex many to one mapping
|
41
|
+
class Model
|
42
|
+
|
43
|
+
include JSONMapper
|
44
|
+
|
45
|
+
# Map the "id", "model_id" or "modelid" attribute (whatever is located first) from the
|
46
|
+
# JSON data structure to the id attribute of the class, using Integer as the data type
|
47
|
+
json_attribute :id, [ :id, :model_id, :modelid ], Integer
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
=== Associations
|
52
|
+
class AssociatedClass
|
53
|
+
|
54
|
+
include JSONMapper
|
55
|
+
|
56
|
+
# Map the "id" of the JSON data structure to the id attribute of the class, using
|
57
|
+
# Integer as the data type
|
58
|
+
json_attribute :id, Integer
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
class Model
|
63
|
+
|
64
|
+
include JSONMapper
|
65
|
+
|
66
|
+
# Map the "association" attribute from the JSON data structure to an instance of
|
67
|
+
# the AssociatedClass class, mapping it to the association attribute of the class.
|
68
|
+
json_attribute :association, AssociatedClass
|
69
|
+
|
70
|
+
# Map all entries in the "associations" array from the JSON data structure to
|
71
|
+
# an array of AssociatedClass instances, mapping them to the associations attribute
|
72
|
+
# of the class
|
73
|
+
json_attributes :associations, AssociatedClass
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
== Requirements
|
78
|
+
|
79
|
+
* {json}[http://rubygems.org/gems/json]
|
80
|
+
|
81
|
+
== Installation
|
82
|
+
|
83
|
+
$ gem install json_mapper
|
84
|
+
|
85
|
+
== Note on Patches/Pull Requests
|
86
|
+
|
87
|
+
* Fork the project.
|
88
|
+
* Make your feature addition or bug fix.
|
89
|
+
* Add tests for it. This is important so I don't break it in a future version unintentionally.
|
90
|
+
* Commit, do not mess with rakefile, version, or history. (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
91
|
+
* Send me a pull request. Bonus points for topic branches.
|
92
|
+
|
93
|
+
== Copyright
|
94
|
+
|
95
|
+
Copyright (c) 2010 Trond Arve Nordheim. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require "rake"
|
2
|
+
require "jeweler"
|
3
|
+
require "bundler"
|
4
|
+
require "rake/testtask"
|
5
|
+
|
6
|
+
# Gemcutter/Jeweler configuration
|
7
|
+
# ----------------------------------------------------------------------------
|
8
|
+
Jeweler::Tasks.new do |gem|
|
9
|
+
|
10
|
+
gem.name = "json_mapper"
|
11
|
+
gem.summary = "Ruby gem for mapping JSON data structures to Ruby classes"
|
12
|
+
gem.email = "tanordheim@gmail.com"
|
13
|
+
gem.homepage = "http://github.com/tanordheim/json_mapper"
|
14
|
+
gem.authors = [ "Trond Arve Nordheim" ]
|
15
|
+
|
16
|
+
gem.add_bundler_dependencies
|
17
|
+
|
18
|
+
end
|
19
|
+
Jeweler::GemcutterTasks.new
|
20
|
+
|
21
|
+
# Test setup
|
22
|
+
# ----------------------------------------------------------------------------
|
23
|
+
Rake::TestTask.new(:test) do |test|
|
24
|
+
test.libs << "lib" << "test"
|
25
|
+
test.ruby_opts << "-rubygems"
|
26
|
+
test.pattern = "test/**/*_test.rb"
|
27
|
+
test.verbose = true
|
28
|
+
end
|
29
|
+
|
30
|
+
# Task setups
|
31
|
+
# ----------------------------------------------------------------------------
|
32
|
+
task :test => :check_dependencies
|
33
|
+
task :default => :test
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.1
|
data/init.rb
ADDED
data/json_mapper.gemspec
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{json_mapper}
|
8
|
+
s.version = "0.1.1"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Trond Arve Nordheim"]
|
12
|
+
s.date = %q{2010-08-08}
|
13
|
+
s.email = %q{tanordheim@gmail.com}
|
14
|
+
s.extra_rdoc_files = [
|
15
|
+
"LICENSE",
|
16
|
+
"README.rdoc"
|
17
|
+
]
|
18
|
+
s.files = [
|
19
|
+
".document",
|
20
|
+
".gitignore",
|
21
|
+
"Gemfile",
|
22
|
+
"LICENSE",
|
23
|
+
"README.rdoc",
|
24
|
+
"Rakefile",
|
25
|
+
"VERSION",
|
26
|
+
"init.rb",
|
27
|
+
"json_mapper.gemspec",
|
28
|
+
"lib/json_mapper.rb",
|
29
|
+
"lib/json_mapper/attribute.rb",
|
30
|
+
"lib/json_mapper/attribute_list.rb",
|
31
|
+
"test.rb",
|
32
|
+
"test/fixtures/complex.json",
|
33
|
+
"test/fixtures/simple.json",
|
34
|
+
"test/json_mapper_test.rb",
|
35
|
+
"test/support/models.rb",
|
36
|
+
"test/test_helper.rb"
|
37
|
+
]
|
38
|
+
s.homepage = %q{http://github.com/tanordheim/json_mapper}
|
39
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
40
|
+
s.require_paths = ["lib"]
|
41
|
+
s.rubygems_version = %q{1.3.7}
|
42
|
+
s.summary = %q{Ruby gem for mapping JSON data structures to Ruby classes}
|
43
|
+
s.test_files = [
|
44
|
+
"test/support/models.rb",
|
45
|
+
"test/test_helper.rb",
|
46
|
+
"test/json_mapper_test.rb"
|
47
|
+
]
|
48
|
+
|
49
|
+
if s.respond_to? :specification_version then
|
50
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
51
|
+
s.specification_version = 3
|
52
|
+
|
53
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
54
|
+
s.add_runtime_dependency(%q<json>, [">= 1.4.3"])
|
55
|
+
s.add_development_dependency(%q<shoulda>, [">= 2.10.3"])
|
56
|
+
s.add_development_dependency(%q<mcmire-matchy>, [">= 0.5.2"])
|
57
|
+
s.add_development_dependency(%q<mocha>, [">= 0.9.8"])
|
58
|
+
else
|
59
|
+
s.add_dependency(%q<json>, [">= 1.4.3"])
|
60
|
+
s.add_dependency(%q<shoulda>, [">= 2.10.3"])
|
61
|
+
s.add_dependency(%q<mcmire-matchy>, [">= 0.5.2"])
|
62
|
+
s.add_dependency(%q<mocha>, [">= 0.9.8"])
|
63
|
+
end
|
64
|
+
else
|
65
|
+
s.add_dependency(%q<json>, [">= 1.4.3"])
|
66
|
+
s.add_dependency(%q<shoulda>, [">= 2.10.3"])
|
67
|
+
s.add_dependency(%q<mcmire-matchy>, [">= 0.5.2"])
|
68
|
+
s.add_dependency(%q<mocha>, [">= 0.9.8"])
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
data/lib/json_mapper.rb
ADDED
@@ -0,0 +1,144 @@
|
|
1
|
+
require "json"
|
2
|
+
|
3
|
+
class Boolean; end
|
4
|
+
|
5
|
+
module JSONMapper
|
6
|
+
|
7
|
+
def self.included(base)
|
8
|
+
base.instance_variable_set("@attributes", {})
|
9
|
+
base.extend ClassMethods
|
10
|
+
end
|
11
|
+
|
12
|
+
module ClassMethods
|
13
|
+
|
14
|
+
def json_attribute(name, *args)
|
15
|
+
|
16
|
+
source_attributes, type = extract_attribute_data(name, *args)
|
17
|
+
attribute = Attribute.new(name, source_attributes, type)
|
18
|
+
@attributes[to_s] ||= []
|
19
|
+
@attributes[to_s] << attribute
|
20
|
+
|
21
|
+
attr_accessor attribute.method_name.to_sym
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
def json_attributes(name, *args)
|
26
|
+
|
27
|
+
source_attributes, type = extract_attribute_data(name, *args)
|
28
|
+
attribute = AttributeList.new(name, source_attributes, type)
|
29
|
+
@attributes[to_s] ||= []
|
30
|
+
@attributes[to_s] << attribute
|
31
|
+
|
32
|
+
attr_accessor attribute.method_name.to_sym
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
def attributes
|
37
|
+
@attributes[to_s] || []
|
38
|
+
end
|
39
|
+
|
40
|
+
def parse(data)
|
41
|
+
|
42
|
+
# Parse the data into a hash
|
43
|
+
json = JSON.parse(data, { :symbolize_names => true })
|
44
|
+
|
45
|
+
# Parse the JSON data structure
|
46
|
+
parse_json(json)
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
def parse_json(json)
|
51
|
+
|
52
|
+
# Create a new instance of ourselves
|
53
|
+
instance = new
|
54
|
+
|
55
|
+
# Instantiate all AttributeList instances
|
56
|
+
attributes.each do |attribute|
|
57
|
+
if attribute.is_a?(AttributeList)
|
58
|
+
instance.send("#{attribute.name}=", attribute.dup)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# Traverse all defined attributes and assign data from the
|
63
|
+
# JSON data structure
|
64
|
+
attributes.each do |attribute|
|
65
|
+
if is_mapped?(attribute, json)
|
66
|
+
value = mapping_value(attribute, json)
|
67
|
+
if attribute.is_a?(AttributeList)
|
68
|
+
value = [ value ] unless value.is_a?(Array)
|
69
|
+
value.each do |v|
|
70
|
+
instance.send("#{attribute.name}") << build_attribute(attribute.name, attribute.type).typecast(v)
|
71
|
+
end
|
72
|
+
else
|
73
|
+
instance.send("#{attribute.name}=".to_sym, attribute.typecast(value))
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
instance
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
private
|
83
|
+
|
84
|
+
def build_attribute(name, type)
|
85
|
+
Attribute.new(name, name, type)
|
86
|
+
end
|
87
|
+
|
88
|
+
def extract_attribute_data(name, *args)
|
89
|
+
|
90
|
+
# If args is not an array, or it contains 0 elements,
|
91
|
+
# throw an argument error as we at least need the data
|
92
|
+
# type for the mapping specified.
|
93
|
+
if !args.is_a?(Array) || args.empty?
|
94
|
+
raise ArgumentError.new("Type parameter is required")
|
95
|
+
end
|
96
|
+
|
97
|
+
# If the first argument is a symbol or an array, that's
|
98
|
+
# a specific source attribute mapping. If not, use the
|
99
|
+
# specified name as the source attribute name.
|
100
|
+
if args[0].is_a?(Symbol) || args[0].is_a?(Array)
|
101
|
+
source_attributes = args.delete_at(0)
|
102
|
+
else
|
103
|
+
source_attributes = name
|
104
|
+
end
|
105
|
+
|
106
|
+
# The remaining first argument must be a valid data type
|
107
|
+
if args[0].is_a?(Class)
|
108
|
+
type = args[0]
|
109
|
+
else
|
110
|
+
raise ArgumentError.new("Invalid type parameter specified")
|
111
|
+
end
|
112
|
+
|
113
|
+
return source_attributes, type
|
114
|
+
|
115
|
+
end
|
116
|
+
|
117
|
+
def is_mapped?(attribute, json)
|
118
|
+
|
119
|
+
attribute.source_attributes.each do |source_attribute|
|
120
|
+
if json.key?(source_attribute)
|
121
|
+
return true
|
122
|
+
end
|
123
|
+
end
|
124
|
+
return false
|
125
|
+
|
126
|
+
end
|
127
|
+
|
128
|
+
def mapping_value(attribute, json)
|
129
|
+
|
130
|
+
attribute.source_attributes.each do |source_attribute|
|
131
|
+
if json.key?(source_attribute)
|
132
|
+
return json[source_attribute]
|
133
|
+
end
|
134
|
+
end
|
135
|
+
return nil
|
136
|
+
|
137
|
+
end
|
138
|
+
|
139
|
+
end
|
140
|
+
|
141
|
+
end
|
142
|
+
|
143
|
+
require "json_mapper/attribute"
|
144
|
+
require "json_mapper/attribute_list"
|
@@ -0,0 +1,40 @@
|
|
1
|
+
class Attribute
|
2
|
+
|
3
|
+
attr_accessor :name, :source_attributes, :type
|
4
|
+
|
5
|
+
Types = [ String, Integer, Boolean ]
|
6
|
+
|
7
|
+
def initialize(name, source_attributes, type)
|
8
|
+
|
9
|
+
self.name = name
|
10
|
+
self.source_attributes = source_attributes.is_a?(Array) ? source_attributes : [ source_attributes ]
|
11
|
+
self.type = type
|
12
|
+
|
13
|
+
end
|
14
|
+
|
15
|
+
def method_name
|
16
|
+
@method_name ||= self.name.to_s.tr("-", "_")
|
17
|
+
end
|
18
|
+
|
19
|
+
def typecast(value)
|
20
|
+
|
21
|
+
return value if value.nil?
|
22
|
+
|
23
|
+
if self.type == String then return value.to_s
|
24
|
+
elsif self.type == Integer then return value.to_i
|
25
|
+
elsif self.type == Boolean then return value.to_s == "true"
|
26
|
+
else
|
27
|
+
|
28
|
+
# If our type is a JSONMapper instance, delegate the
|
29
|
+
# mapping to that class
|
30
|
+
if self.type.new.is_a?(JSONMapper)
|
31
|
+
return self.type.parse_json(value)
|
32
|
+
else
|
33
|
+
return value
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
class AttributeList < ::Array
|
2
|
+
|
3
|
+
attr_accessor :name, :source_attributes, :type
|
4
|
+
|
5
|
+
def initialize(name, source_attributes, type)
|
6
|
+
|
7
|
+
self.name = name
|
8
|
+
self.source_attributes = source_attributes.is_a?(Array) ? source_attributes : [ source_attributes ]
|
9
|
+
self.type = type
|
10
|
+
|
11
|
+
end
|
12
|
+
|
13
|
+
def method_name
|
14
|
+
@method_name ||= self.name.to_s.tr("-", "_")
|
15
|
+
end
|
16
|
+
|
17
|
+
def typecast
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
data/test.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
module TestModule
|
2
|
+
def self.included(base)
|
3
|
+
base.extend ClassMethods
|
4
|
+
end
|
5
|
+
|
6
|
+
module ClassMethods
|
7
|
+
def foo
|
8
|
+
attr_accessor :test
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class TestClass
|
14
|
+
include TestModule
|
15
|
+
foo
|
16
|
+
end
|
17
|
+
|
18
|
+
t = TestClass.new
|
19
|
+
t.test = "test"
|
20
|
+
puts "Test is #{t.test}"
|
21
|
+
|
22
|
+
t2 = Class.new do
|
23
|
+
include TestModule
|
24
|
+
foo
|
25
|
+
end
|
26
|
+
|
27
|
+
t2.test = "foo"
|
28
|
+
puts "Test is #{t2.test}"
|
@@ -0,0 +1,21 @@
|
|
1
|
+
{
|
2
|
+
"id": 1,
|
3
|
+
"title": "Complex JSON title",
|
4
|
+
"simple": {
|
5
|
+
"id": 1,
|
6
|
+
"title": "Simple JSON title",
|
7
|
+
"boolean": true
|
8
|
+
},
|
9
|
+
"simples": [
|
10
|
+
{
|
11
|
+
"id": 1,
|
12
|
+
"title": "Simple JSON title #1",
|
13
|
+
"boolean": true
|
14
|
+
},
|
15
|
+
{
|
16
|
+
"id": 2,
|
17
|
+
"title": "Simple JSON title #2",
|
18
|
+
"boolean": true
|
19
|
+
}
|
20
|
+
]
|
21
|
+
}
|
@@ -0,0 +1,104 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
require "support/models"
|
3
|
+
|
4
|
+
class JSONMapperTest < Test::Unit::TestCase
|
5
|
+
|
6
|
+
context "included in a model class" do
|
7
|
+
|
8
|
+
setup do
|
9
|
+
@klass = Class.new do
|
10
|
+
include JSONMapper
|
11
|
+
def to_s
|
12
|
+
"TestUnitClass"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
should "initialize empty attributes array" do
|
18
|
+
@klass.attributes.should == []
|
19
|
+
end
|
20
|
+
|
21
|
+
should "allow adding a simple attribute mapping" do
|
22
|
+
|
23
|
+
@klass.json_attribute :id, Integer
|
24
|
+
|
25
|
+
@klass.attributes.size.should == 1
|
26
|
+
@klass.attributes.first.name.should == :id
|
27
|
+
@klass.attributes.first.source_attributes.should == [ :id ]
|
28
|
+
@klass.attributes.first.type.should == Integer
|
29
|
+
@klass.attributes.first.method_name.should == "id"
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
should "allow adding a complex attribute mapping" do
|
34
|
+
@klass.json_attribute :id, [ :id, :attribute_id, :foo_id ], Integer
|
35
|
+
@klass.attributes.size.should == 1
|
36
|
+
@klass.attributes.first.name.should == :id
|
37
|
+
@klass.attributes.first.source_attributes.should == [ :id, :attribute_id, :foo_id ]
|
38
|
+
@klass.attributes.first.type.should == Integer
|
39
|
+
@klass.attributes.first.method_name.should == "id"
|
40
|
+
end
|
41
|
+
|
42
|
+
should "parse simple json structure into a ruby object" do
|
43
|
+
model = SimpleModel.parse(fixture_file("simple.json"))
|
44
|
+
model.id.should == 1
|
45
|
+
model.title.should == "Simple JSON title"
|
46
|
+
model.boolean.should == true
|
47
|
+
end
|
48
|
+
|
49
|
+
should "assign value from different sources into an attribute" do
|
50
|
+
|
51
|
+
model = ComplexModel.parse('{ "id": 1 }')
|
52
|
+
model.id.should == 1
|
53
|
+
|
54
|
+
model = ComplexModel.parse('{ "attribute_id": 1 }')
|
55
|
+
model.id.should == 1
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
should "not overwrite initial value when assigning values from different sources into an attribute" do
|
60
|
+
|
61
|
+
model = ComplexModel.parse('{ "id": 1, "attribute_id": 2 }')
|
62
|
+
model.id.should == 1
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
should "assign another model into an attribute" do
|
67
|
+
|
68
|
+
model = ComplexModel.parse('{ "simple": { "id": 1 } }')
|
69
|
+
model.simple.id.should == 1
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
should "assign an array into an attribute" do
|
74
|
+
|
75
|
+
model = ComplexModel.parse('{ "integers": [ 1, 2, 3 ] }')
|
76
|
+
model.integers.should == [ 1, 2, 3 ]
|
77
|
+
|
78
|
+
end
|
79
|
+
|
80
|
+
should "assign an array of models into an attribute" do
|
81
|
+
|
82
|
+
model = ComplexModel.parse('{ "simples": [{ "id": 1 }, { "id": 2 }] }')
|
83
|
+
model.simples.size.should == 2
|
84
|
+
model.simples.first.id.should == 1
|
85
|
+
model.simples.last.id.should == 2
|
86
|
+
|
87
|
+
end
|
88
|
+
|
89
|
+
should "parse complex json structure into a ruby object" do
|
90
|
+
model = ComplexModel.parse(fixture_file("complex.json"))
|
91
|
+
model.id.should == 1
|
92
|
+
model.model_title.should == "Complex JSON title"
|
93
|
+
model.simple.id.should == 1
|
94
|
+
model.simple.title.should == "Simple JSON title"
|
95
|
+
model.simples.size.should == 2
|
96
|
+
model.simples.first.id.should == 1
|
97
|
+
model.simples.first.title.should == "Simple JSON title #1"
|
98
|
+
model.simples.last.id.should == 2
|
99
|
+
model.simples.last.title.should == "Simple JSON title #2"
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
class SimpleModel
|
2
|
+
|
3
|
+
include JSONMapper
|
4
|
+
|
5
|
+
json_attribute :id, Integer
|
6
|
+
json_attribute :title, String
|
7
|
+
json_attribute :boolean, Boolean
|
8
|
+
|
9
|
+
end
|
10
|
+
|
11
|
+
class ComplexModel
|
12
|
+
|
13
|
+
include JSONMapper
|
14
|
+
|
15
|
+
json_attribute :id, [ :id, :attribute_id ], Integer
|
16
|
+
json_attribute :model_title, :title, String
|
17
|
+
json_attribute :simple, SimpleModel
|
18
|
+
json_attributes :simples, SimpleModel
|
19
|
+
json_attributes :integers, Integer
|
20
|
+
|
21
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require "test/unit"
|
2
|
+
require "shoulda"
|
3
|
+
require "matchy"
|
4
|
+
require "mocha"
|
5
|
+
|
6
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
7
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
8
|
+
require "json_mapper"
|
9
|
+
|
10
|
+
class Test::Unit::TestCase
|
11
|
+
end
|
12
|
+
|
13
|
+
# Load a fixture file and return the contents
|
14
|
+
def fixture_file(filename)
|
15
|
+
|
16
|
+
return "" if filename == ""
|
17
|
+
file_path = File.expand_path(File.dirname(__FILE__) + "/fixtures/" + filename)
|
18
|
+
File.read(file_path)
|
19
|
+
|
20
|
+
end
|
metadata
ADDED
@@ -0,0 +1,150 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: json_mapper
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 25
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 1
|
10
|
+
version: 0.1.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Trond Arve Nordheim
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-08-08 00:00:00 +02:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
prerelease: false
|
23
|
+
name: json
|
24
|
+
version_requirements: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 1
|
30
|
+
segments:
|
31
|
+
- 1
|
32
|
+
- 4
|
33
|
+
- 3
|
34
|
+
version: 1.4.3
|
35
|
+
requirement: *id001
|
36
|
+
type: :runtime
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
prerelease: false
|
39
|
+
name: shoulda
|
40
|
+
version_requirements: &id002 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
hash: 33
|
46
|
+
segments:
|
47
|
+
- 2
|
48
|
+
- 10
|
49
|
+
- 3
|
50
|
+
version: 2.10.3
|
51
|
+
requirement: *id002
|
52
|
+
type: :development
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
prerelease: false
|
55
|
+
name: mcmire-matchy
|
56
|
+
version_requirements: &id003 !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
hash: 15
|
62
|
+
segments:
|
63
|
+
- 0
|
64
|
+
- 5
|
65
|
+
- 2
|
66
|
+
version: 0.5.2
|
67
|
+
requirement: *id003
|
68
|
+
type: :development
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
prerelease: false
|
71
|
+
name: mocha
|
72
|
+
version_requirements: &id004 !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ">="
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
hash: 43
|
78
|
+
segments:
|
79
|
+
- 0
|
80
|
+
- 9
|
81
|
+
- 8
|
82
|
+
version: 0.9.8
|
83
|
+
requirement: *id004
|
84
|
+
type: :development
|
85
|
+
description:
|
86
|
+
email: tanordheim@gmail.com
|
87
|
+
executables: []
|
88
|
+
|
89
|
+
extensions: []
|
90
|
+
|
91
|
+
extra_rdoc_files:
|
92
|
+
- LICENSE
|
93
|
+
- README.rdoc
|
94
|
+
files:
|
95
|
+
- .document
|
96
|
+
- .gitignore
|
97
|
+
- Gemfile
|
98
|
+
- LICENSE
|
99
|
+
- README.rdoc
|
100
|
+
- Rakefile
|
101
|
+
- VERSION
|
102
|
+
- init.rb
|
103
|
+
- json_mapper.gemspec
|
104
|
+
- lib/json_mapper.rb
|
105
|
+
- lib/json_mapper/attribute.rb
|
106
|
+
- lib/json_mapper/attribute_list.rb
|
107
|
+
- test.rb
|
108
|
+
- test/fixtures/complex.json
|
109
|
+
- test/fixtures/simple.json
|
110
|
+
- test/json_mapper_test.rb
|
111
|
+
- test/support/models.rb
|
112
|
+
- test/test_helper.rb
|
113
|
+
has_rdoc: true
|
114
|
+
homepage: http://github.com/tanordheim/json_mapper
|
115
|
+
licenses: []
|
116
|
+
|
117
|
+
post_install_message:
|
118
|
+
rdoc_options:
|
119
|
+
- --charset=UTF-8
|
120
|
+
require_paths:
|
121
|
+
- lib
|
122
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
123
|
+
none: false
|
124
|
+
requirements:
|
125
|
+
- - ">="
|
126
|
+
- !ruby/object:Gem::Version
|
127
|
+
hash: 3
|
128
|
+
segments:
|
129
|
+
- 0
|
130
|
+
version: "0"
|
131
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
132
|
+
none: false
|
133
|
+
requirements:
|
134
|
+
- - ">="
|
135
|
+
- !ruby/object:Gem::Version
|
136
|
+
hash: 3
|
137
|
+
segments:
|
138
|
+
- 0
|
139
|
+
version: "0"
|
140
|
+
requirements: []
|
141
|
+
|
142
|
+
rubyforge_project:
|
143
|
+
rubygems_version: 1.3.7
|
144
|
+
signing_key:
|
145
|
+
specification_version: 3
|
146
|
+
summary: Ruby gem for mapping JSON data structures to Ruby classes
|
147
|
+
test_files:
|
148
|
+
- test/support/models.rb
|
149
|
+
- test/test_helper.rb
|
150
|
+
- test/json_mapper_test.rb
|