objectable_json 0.1.0
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.
- checksums.yaml +7 -0
- data/.gitignore +13 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/Guardfile +42 -0
- data/LICENSE.txt +21 -0
- data/README.md +258 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/circle.yml +7 -0
- data/circleci.yml +7 -0
- data/lib/objectable_json/klass_creator.rb +60 -0
- data/lib/objectable_json/version.rb +3 -0
- data/lib/objectable_json.rb +125 -0
- data/objectable_json.gemspec +30 -0
- metadata +175 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c43479430ce50d59a60e4e800633efa51edbeb95
|
4
|
+
data.tar.gz: 2c3b015a75ce7c49c0ade75cd330eccf594c3aa0
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 21dbf1e2478123acafa949875959839d311f100bbffaa410aa763aae02cbba442a1df3215b5ed856cc3e9f93f80840eaeaf929bceedf99a85fff66f7a208945b
|
7
|
+
data.tar.gz: 1693ea08fbfde36bbe0fb813e361925ef15efb4f328f1da9dea7165b8cbd0905d42fb532706b06e5918e2db6e54752b8167a02e8e07cfc875be109ea1652c0c0
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/Gemfile
ADDED
data/Guardfile
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
# A sample Guardfile
|
2
|
+
# More info at https://github.com/guard/guard#readme
|
3
|
+
|
4
|
+
## Uncomment and set this to only include directories you want to watch
|
5
|
+
# directories %w(app lib config test spec features) \
|
6
|
+
# .select{|d| Dir.exists?(d) ? d : UI.warning("Directory #{d} does not exist")}
|
7
|
+
|
8
|
+
## Note: if you are using the `directories` clause above and you are not
|
9
|
+
## watching the project directory ('.'), then you will want to move
|
10
|
+
## the Guardfile to a watched dir and symlink it back, e.g.
|
11
|
+
#
|
12
|
+
# $ mkdir config
|
13
|
+
# $ mv Guardfile config/
|
14
|
+
# $ ln -s config/Guardfile .
|
15
|
+
#
|
16
|
+
# and, you'll have to watch "config/Guardfile" instead of "Guardfile"
|
17
|
+
|
18
|
+
# Note: The cmd option is now required due to the increasing number of ways
|
19
|
+
# rspec may be run, below are examples of the most common uses.
|
20
|
+
# * bundler: 'bundle exec rspec'
|
21
|
+
# * bundler binstubs: 'bin/rspec'
|
22
|
+
# * spring: 'bin/rspec' (This will use spring if running and you have
|
23
|
+
# installed the spring binstubs per the docs)
|
24
|
+
# * zeus: 'zeus rspec' (requires the server to be started separately)
|
25
|
+
# * 'just' rspec: 'rspec'
|
26
|
+
|
27
|
+
guard :rspec, cmd: "bundle exec rspec" do
|
28
|
+
require "guard/rspec/dsl"
|
29
|
+
dsl = Guard::RSpec::Dsl.new(self)
|
30
|
+
|
31
|
+
# Feel free to open issues for suggestions and improvements
|
32
|
+
|
33
|
+
# RSpec files
|
34
|
+
rspec = dsl.rspec
|
35
|
+
watch(rspec.spec_helper) { rspec.spec_dir }
|
36
|
+
watch(rspec.spec_support) { rspec.spec_dir }
|
37
|
+
watch(rspec.spec_files)
|
38
|
+
|
39
|
+
# Ruby files
|
40
|
+
ruby = dsl.ruby
|
41
|
+
dsl.watch_spec_files_for(ruby.lib_files)
|
42
|
+
end
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2016 kazuooooo
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,258 @@
|
|
1
|
+
[](LICENSE)
|
2
|
+
[](https://circleci.com/gh/kazuooooo/objectable-json)
|
3
|
+
# ObjectableJSON
|
4
|
+
|
5
|
+
ObjectableJSON is simple and clever JSON => Object Mapper. ObjectableJSON automatically analyze your JSON values and convert the values to Single Object. So, you can easily convert JSON to Single Object by only calling ObjectableJSON#parse method.
|
6
|
+
Especially, this gem is powerful & useful when you treat some API JSON response.
|
7
|
+
Also, this gem can work for Hash.
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
Add this line to your application's Gemfile:
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
gem 'objectable_json'
|
15
|
+
```
|
16
|
+
|
17
|
+
And then execute:
|
18
|
+
|
19
|
+
$ bundle
|
20
|
+
|
21
|
+
Or install it yourself as:
|
22
|
+
|
23
|
+
$ gem install objectable_json
|
24
|
+
|
25
|
+
## Usage
|
26
|
+
For example, you get some API response JSON like this
|
27
|
+
```ruby
|
28
|
+
{
|
29
|
+
"user": {
|
30
|
+
"first_name": "kazuya",
|
31
|
+
"last_name": "matsumoto"
|
32
|
+
}
|
33
|
+
}
|
34
|
+
```
|
35
|
+
If you need user first_name, maybe you will write code like this.
|
36
|
+
```ruby
|
37
|
+
response = JSON.parse(json_response)
|
38
|
+
first_name = response["user"]["first_name"]
|
39
|
+
```
|
40
|
+
This code is little verbose because of two raw string hash key. If you have to access deeper nest, code will become more messy.
|
41
|
+
|
42
|
+
By using ObjectableJSON, you can write first_name access more simple.
|
43
|
+
```ruby
|
44
|
+
response = ObjectableJSON.parse(json_response)
|
45
|
+
first_name = response.user.first_name
|
46
|
+
```
|
47
|
+
Cool! You can access response values with dot chain.
|
48
|
+
|
49
|
+
ObjectableJSON automatically analyze your JSON values and convert it to single object.
|
50
|
+
In this case, ObjectedJSON & User Object is created and set instance variable like this.
|
51
|
+
```ruby
|
52
|
+
# define class like this
|
53
|
+
# top level class. This class has User class object as attribute.
|
54
|
+
class ObjectedJSON
|
55
|
+
attr_accessor: :user
|
56
|
+
def initialize(args)
|
57
|
+
@user = args[:user]
|
58
|
+
end
|
59
|
+
end
|
60
|
+
# user object. first_name & last_name are defined as attributes.
|
61
|
+
class ObjectedJSON::User
|
62
|
+
attr_accessor: :first_name, :last_name
|
63
|
+
def initialize(args)
|
64
|
+
@first_name = args[:first_name]
|
65
|
+
@last_name = args[:last_name]
|
66
|
+
end
|
67
|
+
end
|
68
|
+
# created object with setting
|
69
|
+
values
|
70
|
+
response = ObjectableJSON.parse(json_response)
|
71
|
+
=> #<ObjectedJSON:0x007f9718b60100 @user=#<ObjectedJSON::User:0x007f9718b607e0 @first_name="matsumoto", @last_name="kazuya">>
|
72
|
+
```
|
73
|
+
|
74
|
+
ObjectableJSON defines classes, So you can easily definine method to JSON attributes.
|
75
|
+
```ruby
|
76
|
+
response.user.class_eval do
|
77
|
+
def full_name
|
78
|
+
first_name + last_name
|
79
|
+
end
|
80
|
+
end
|
81
|
+
response.user.full_name
|
82
|
+
=> "matsumotokauzya"
|
83
|
+
```
|
84
|
+
|
85
|
+
Also, if you get hash array JSON like this
|
86
|
+
```ruby
|
87
|
+
{
|
88
|
+
"user": {
|
89
|
+
"friends": [
|
90
|
+
{
|
91
|
+
"name": "yamada",
|
92
|
+
"sex": "male"
|
93
|
+
},
|
94
|
+
{
|
95
|
+
"name": "sato",
|
96
|
+
"sex": "female"
|
97
|
+
},
|
98
|
+
{
|
99
|
+
"name": "john",
|
100
|
+
"sex": "male",
|
101
|
+
"country": "us"
|
102
|
+
}
|
103
|
+
]
|
104
|
+
}
|
105
|
+
}
|
106
|
+
```
|
107
|
+
friends is recognized as Friend Object Array. (plural is renamed to singular only if it is available)
|
108
|
+
```ruby
|
109
|
+
response = ObjectableJSON.parse(json_response, 'SimpleAPI') # you can optionally set top level name space
|
110
|
+
|
111
|
+
friends = response.user.friends
|
112
|
+
=> [#<SimpleAPI::Friend:0x007fcfec305728 @name="yamada", @sex="male">,
|
113
|
+
#<SimpleAPI::Friend:0x007fcfec3048a0 @name="sato", @sex="female">,
|
114
|
+
#<SimpleAPI::Friend:0x007fcfec2feba8 @country="us", @name="john", @sex="male">]
|
115
|
+
|
116
|
+
friends.map(&:name)
|
117
|
+
=> ["yamada", "sato", "john"]
|
118
|
+
```
|
119
|
+
|
120
|
+
At last, let me introduce real GoogleMapAPI example.
|
121
|
+
This is JSON response
|
122
|
+
```ruby
|
123
|
+
{
|
124
|
+
"results" : [
|
125
|
+
{
|
126
|
+
"address_components" : [
|
127
|
+
{
|
128
|
+
"long_name" : "1600",
|
129
|
+
"short_name" : "1600",
|
130
|
+
"types" : [ "street_number" ]
|
131
|
+
},
|
132
|
+
{
|
133
|
+
"long_name" : "Amphitheatre Pkwy",
|
134
|
+
"short_name" : "Amphitheatre Pkwy",
|
135
|
+
"types" : [ "route" ]
|
136
|
+
},
|
137
|
+
{
|
138
|
+
"long_name" : "Mountain View",
|
139
|
+
"short_name" : "Mountain View",
|
140
|
+
"types" : [ "locality", "political" ]
|
141
|
+
},
|
142
|
+
{
|
143
|
+
"long_name" : "Santa Clara County",
|
144
|
+
"short_name" : "Santa Clara County",
|
145
|
+
"types" : [ "administrative_area_level_2", "political" ]
|
146
|
+
},
|
147
|
+
{
|
148
|
+
"long_name" : "California",
|
149
|
+
"short_name" : "CA",
|
150
|
+
"types" : [ "administrative_area_level_1", "political" ]
|
151
|
+
},
|
152
|
+
{
|
153
|
+
"long_name" : "United States",
|
154
|
+
"short_name" : "US",
|
155
|
+
"types" : [ "country", "political" ]
|
156
|
+
},
|
157
|
+
{
|
158
|
+
"long_name" : "94043",
|
159
|
+
"short_name" : "94043",
|
160
|
+
"types" : [ "postal_code" ]
|
161
|
+
}
|
162
|
+
],
|
163
|
+
"formatted_address" : "1600 Amphitheatre Parkway, Mountain View, CA 94043, USA",
|
164
|
+
"geometry" : {
|
165
|
+
"location" : {
|
166
|
+
"lat" : 37.4224764,
|
167
|
+
"lng" : -122.0842499
|
168
|
+
},
|
169
|
+
"location_type" : "ROOFTOP",
|
170
|
+
"viewport" : {
|
171
|
+
"northeast" : {
|
172
|
+
"lat" : 37.4238253802915,
|
173
|
+
"lng" : -122.0829009197085
|
174
|
+
},
|
175
|
+
"southwest" : {
|
176
|
+
"lat" : 37.4211274197085,
|
177
|
+
"lng" : -122.0855988802915
|
178
|
+
}
|
179
|
+
}
|
180
|
+
},
|
181
|
+
"place_id" : "ChIJ2eUgeAK6j4ARbn5u_wAGqWA",
|
182
|
+
"types" : [ "street_address" ]
|
183
|
+
}
|
184
|
+
],
|
185
|
+
"status" : "OK"
|
186
|
+
}
|
187
|
+
```
|
188
|
+
|
189
|
+
This is converted result
|
190
|
+
```ruby
|
191
|
+
ObjectableJSON.parse(google_map_api_response, 'GoogleMapAPIWrapper')
|
192
|
+
=> [#<GoogleMapAPIWrapper::Result:0x007fb3cb1ddba8
|
193
|
+
@address_components=
|
194
|
+
[#<GoogleMapAPIWrapper::AddressComponent:0x007fb3cb216d40
|
195
|
+
@long_name="1600",
|
196
|
+
@short_name="1600",
|
197
|
+
@types=["street_number"]>,
|
198
|
+
#<GoogleMapAPIWrapper::AddressComponent:0x007fb3cb20dd80
|
199
|
+
@long_name="Amphitheatre Pkwy",
|
200
|
+
@short_name="Amphitheatre Pkwy",
|
201
|
+
@types=["route"]>,
|
202
|
+
#<GoogleMapAPIWrapper::AddressComponent:0x007fb3cb20c250
|
203
|
+
@long_name="Mountain View",
|
204
|
+
@short_name="Mountain View",
|
205
|
+
@types=["locality", "political"]>,
|
206
|
+
#<GoogleMapAPIWrapper::AddressComponent:0x007fb3ca988778
|
207
|
+
@long_name="Santa Clara County",
|
208
|
+
@short_name="Santa Clara County",
|
209
|
+
@types=["administrative_area_level_2", "political"]>,
|
210
|
+
#<GoogleMapAPIWrapper::AddressComponent:0x007fb3cb2054c8
|
211
|
+
@long_name="California",
|
212
|
+
@short_name="CA",
|
213
|
+
@types=["administrative_area_level_1", "political"]>,
|
214
|
+
#<GoogleMapAPIWrapper::AddressComponent:0x007fb3ca9816d0
|
215
|
+
@long_name="United States",
|
216
|
+
@short_name="US",
|
217
|
+
@types=["country", "political"]>,
|
218
|
+
#<GoogleMapAPIWrapper::AddressComponent:0x007fb3ca97a240
|
219
|
+
@long_name="94043",
|
220
|
+
@short_name="94043",
|
221
|
+
@types=["postal_code"]>],
|
222
|
+
@formatted_address="1600 Amphitheatre Parkway, Mountain View, CA 94043, USA",
|
223
|
+
@geometry=
|
224
|
+
#<GoogleMapAPIWrapper::Geometry:0x007fb3cb1f6a18
|
225
|
+
@location=
|
226
|
+
#<GoogleMapAPIWrapper::Location:0x007fb3ca973cb0
|
227
|
+
@lat=37.4224764,
|
228
|
+
@lng=-122.0842499>,
|
229
|
+
@location_type="ROOFTOP",
|
230
|
+
@viewport=
|
231
|
+
#<GoogleMapAPIWrapper::Viewport:0x007fb3cb1f6270
|
232
|
+
@northeast=
|
233
|
+
#<GoogleMapAPIWrapper::Northeast:0x007fb3ca971bb8
|
234
|
+
@lat=37.4238253802915,
|
235
|
+
@lng=-122.0829009197085>,
|
236
|
+
@southwest=
|
237
|
+
#<GoogleMapAPIWrapper::Southwest:0x007fb3ca9703f8
|
238
|
+
@lat=37.4211274197085,
|
239
|
+
@lng=-122.0855988802915>>>,
|
240
|
+
@place_id="ChIJ2eUgeAK6j4ARbn5u_wAGqWA",
|
241
|
+
@types=["street_address"]>]
|
242
|
+
```
|
243
|
+
You can treat complex API with more simple and clean code.
|
244
|
+
|
245
|
+
## Development
|
246
|
+
|
247
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
248
|
+
|
249
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
250
|
+
|
251
|
+
## Contributing
|
252
|
+
|
253
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/objectable_json.
|
254
|
+
(very very welcome :) )
|
255
|
+
|
256
|
+
## License
|
257
|
+
|
258
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "objectable_json"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start
|
data/bin/setup
ADDED
data/circle.yml
ADDED
data/circleci.yml
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'objectable_json'
|
2
|
+
module ObjectableJSON::KlassCreator
|
3
|
+
class << self
|
4
|
+
attr_accessor :name_space
|
5
|
+
# create class
|
6
|
+
# @param klass_name [String] class name
|
7
|
+
# @param attribute_names [Hash] attributes_hash is set as class instance attribute_names named key
|
8
|
+
# @return [Class] created class object
|
9
|
+
def create_klass(klass_name, attribute_names)
|
10
|
+
full_klass_name = full_klass_name(klass_name)
|
11
|
+
define_klass(name_space.constantize, klass_name)
|
12
|
+
define_attributes(full_klass_name, attribute_names)
|
13
|
+
full_klass_name.constantize
|
14
|
+
end
|
15
|
+
|
16
|
+
# set name space. define this name space class on callback
|
17
|
+
# @param name_space [String] top name space
|
18
|
+
def name_space=(name_space)
|
19
|
+
@name_space = name_space.camelize
|
20
|
+
define_klass(Object, name_space)
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
# define empty class
|
26
|
+
# @param name_space [Class]
|
27
|
+
# @param klass_name [String]
|
28
|
+
# @return nil
|
29
|
+
def define_klass(name_space, klass_name)
|
30
|
+
unless const_defined? full_klass_name(klass_name)
|
31
|
+
klass_obj = Class.new(Object) {}
|
32
|
+
name_space.const_set(klass_name.camelize, klass_obj)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# define new attributes to class
|
37
|
+
# @param klass_name [String]
|
38
|
+
# @param attributes_names [Array] array of attribute names
|
39
|
+
# @return nil
|
40
|
+
def define_attributes(klass_name, attributes_names)
|
41
|
+
klass_name.constantize.class_eval do
|
42
|
+
attr_accessor(* attributes_names)
|
43
|
+
|
44
|
+
def initialize(attributes)
|
45
|
+
attributes.each do |k, v|
|
46
|
+
instance_variable_set("@#{k}", v)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# get full class name
|
53
|
+
# @param klass_name [String]
|
54
|
+
# @return [String] full class name
|
55
|
+
def full_klass_name(klass_name)
|
56
|
+
return klass_name if klass_name == name_space
|
57
|
+
name_space + "::" + klass_name.camelize
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
require 'active_support'
|
2
|
+
require 'active_support/core_ext'
|
3
|
+
require 'objectable_json/klass_creator'
|
4
|
+
|
5
|
+
module ObjectableJSON
|
6
|
+
class << self
|
7
|
+
# parse JSON/Hash to ObjectedJSON
|
8
|
+
# @param json_or_hash[JSON/Hash] json_or_hash object
|
9
|
+
# @param name_space[String] top name space
|
10
|
+
# @return [ObjectedJSON] ObjectedJSON object(class name is set as top_name_space arg dynamically)
|
11
|
+
def parse(json_or_hash, name_space = 'ObjectedJSON')
|
12
|
+
KlassCreator.name_space = name_space
|
13
|
+
hash = convert_to_hash(json_or_hash)
|
14
|
+
build(name_space, hash)
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
# build objected json object
|
19
|
+
# @param klass_name [String] klass_name
|
20
|
+
# @param raw_attrs [Hash] klass attribute_names
|
21
|
+
# @return [ObjectedJSON(top_klass_name)] objected json
|
22
|
+
def build(klass_name, raw_attrs)
|
23
|
+
attributes = build_attributes(raw_attrs)
|
24
|
+
klass = KlassCreator.create_klass(klass_name, raw_attrs.keys)
|
25
|
+
klass.new(attributes)
|
26
|
+
end
|
27
|
+
|
28
|
+
# build class attributes.
|
29
|
+
# if raw_attrs values includes hash, the hash convert to object recursively.
|
30
|
+
# @param raw_attrs [Hash] raw attributes hash
|
31
|
+
# @return [Hash] objected attributes hash
|
32
|
+
def build_attributes(raw_attrs)
|
33
|
+
attributes = {}
|
34
|
+
raw_attrs.each do |attr_key, attr_val|
|
35
|
+
attributes[attr_key] =
|
36
|
+
if klassable?({ attr_key => attr_val })
|
37
|
+
build(attr_key, attr_val)
|
38
|
+
elsif attr_val.instance_of?(Array)
|
39
|
+
attr_val.map do |v|
|
40
|
+
value = need_klass_name?(v) ? add_klass_name(attr_key.singularize, v) : v
|
41
|
+
klassable?(value) ? build(value.keys.first, value.values.first) : value
|
42
|
+
end
|
43
|
+
else
|
44
|
+
attr_val
|
45
|
+
end
|
46
|
+
end
|
47
|
+
attributes
|
48
|
+
end
|
49
|
+
|
50
|
+
# check value is can be convert to class or not
|
51
|
+
# it return true attr_val has class name(hash key) & values(hash val) like this
|
52
|
+
# @example
|
53
|
+
# {
|
54
|
+
# "user" => {
|
55
|
+
# "email" => "hoge@baz.com",
|
56
|
+
# "sex"=>=> "male"
|
57
|
+
# }
|
58
|
+
# }
|
59
|
+
def klassable?(attr_val)
|
60
|
+
attr_val.instance_of?(Hash) && attr_val.values.first.instance_of?(Hash)
|
61
|
+
end
|
62
|
+
|
63
|
+
# judge need to add klass name to hash
|
64
|
+
# @see ObjectableJSON::Builder.add_klass_name
|
65
|
+
# @param attr_val
|
66
|
+
# @return [Boolean] need to add klass name or not
|
67
|
+
def need_klass_name?(attr_val)
|
68
|
+
!klassable?(attr_val) && attr_val.instance_of?(Hash)
|
69
|
+
end
|
70
|
+
|
71
|
+
# add klass name to hash
|
72
|
+
# if hash has hash array like this
|
73
|
+
# @example
|
74
|
+
# {
|
75
|
+
# "friends" => [
|
76
|
+
# {
|
77
|
+
# "name" => "yamada",
|
78
|
+
# "sex" => "male"
|
79
|
+
# },
|
80
|
+
# {
|
81
|
+
# "name" => "sato",
|
82
|
+
# "sex" => "female"
|
83
|
+
# },
|
84
|
+
# {
|
85
|
+
# "name" => "john",
|
86
|
+
# "sex" => "male",
|
87
|
+
# "country" => "us"
|
88
|
+
# }
|
89
|
+
# ]
|
90
|
+
# }
|
91
|
+
# this hash array need class name, so 'friend' key complemented hash like this
|
92
|
+
# (class name is singularized only singularize method available)
|
93
|
+
# @example
|
94
|
+
# {
|
95
|
+
# "friends" => [
|
96
|
+
# "friend" => {
|
97
|
+
# "name" => "yamada",
|
98
|
+
# "sex" => "male"
|
99
|
+
# },
|
100
|
+
# "friend" => {
|
101
|
+
# "name" => "sato",
|
102
|
+
# "sex" => "female"
|
103
|
+
# },
|
104
|
+
# "friend" => {
|
105
|
+
# "name" => "john",
|
106
|
+
# "sex" => "male",
|
107
|
+
# "country" => "us"
|
108
|
+
# }
|
109
|
+
# ]
|
110
|
+
# }
|
111
|
+
def add_klass_name(klass_name, attributes)
|
112
|
+
{ klass_name.singularize => attributes }
|
113
|
+
end
|
114
|
+
|
115
|
+
# convert json to hash if needed
|
116
|
+
# @param json_or_hash
|
117
|
+
# @return [Hash]
|
118
|
+
def convert_to_hash(json_or_hash)
|
119
|
+
json_or_hash.instance_of?(Hash) ? json_or_hash : JSON.parse(json_or_hash)
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'objectable_json/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "objectable_json"
|
8
|
+
spec.version = ObjectableJSON::VERSION
|
9
|
+
spec.authors = ["kazuooooo"]
|
10
|
+
spec.email = ["matsumotokazuya7@gmail.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{simple and clever JSON => Object Mapper}
|
13
|
+
spec.description = %q{ObjectableJSON is simple and clever JSON => Object Mapper. ObjectableJSON automatically analyze your JSON values and convert the values to Single Object. So, you can easily convert JSON to Single Object by only calling ObjectableJSON#parse method. Especially, this gem is powerful & useful when you treat some API JSON response. Also, this gem can work for Hash.}
|
14
|
+
spec.homepage = "https://github.com/kazuooooo/objectable-json"
|
15
|
+
spec.license = "MIT"
|
16
|
+
|
17
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
18
|
+
spec.bindir = "exe"
|
19
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
20
|
+
spec.require_paths = ["lib"]
|
21
|
+
|
22
|
+
spec.add_development_dependency "bundler", "~> 1.11"
|
23
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
24
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
25
|
+
spec.add_development_dependency "guard", "~> 2.14.0"
|
26
|
+
spec.add_development_dependency "guard-rspec", "~> 4.7.3"
|
27
|
+
spec.add_development_dependency "simplecov", "~> 0.12.0"
|
28
|
+
spec.add_development_dependency "yard"
|
29
|
+
spec.add_dependency "activesupport", "~> 4.0.0"
|
30
|
+
end
|
metadata
ADDED
@@ -0,0 +1,175 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: objectable_json
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- kazuooooo
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-01-07 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.11'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.11'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: guard
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 2.14.0
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 2.14.0
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: guard-rspec
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 4.7.3
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 4.7.3
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: simplecov
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 0.12.0
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 0.12.0
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: yard
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: activesupport
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 4.0.0
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: 4.0.0
|
125
|
+
description: ObjectableJSON is simple and clever JSON => Object Mapper. ObjectableJSON
|
126
|
+
automatically analyze your JSON values and convert the values to Single Object.
|
127
|
+
So, you can easily convert JSON to Single Object by only calling ObjectableJSON#parse
|
128
|
+
method. Especially, this gem is powerful & useful when you treat some API JSON response.
|
129
|
+
Also, this gem can work for Hash.
|
130
|
+
email:
|
131
|
+
- matsumotokazuya7@gmail.com
|
132
|
+
executables: []
|
133
|
+
extensions: []
|
134
|
+
extra_rdoc_files: []
|
135
|
+
files:
|
136
|
+
- ".gitignore"
|
137
|
+
- ".rspec"
|
138
|
+
- Gemfile
|
139
|
+
- Guardfile
|
140
|
+
- LICENSE.txt
|
141
|
+
- README.md
|
142
|
+
- Rakefile
|
143
|
+
- bin/console
|
144
|
+
- bin/setup
|
145
|
+
- circle.yml
|
146
|
+
- circleci.yml
|
147
|
+
- lib/objectable_json.rb
|
148
|
+
- lib/objectable_json/klass_creator.rb
|
149
|
+
- lib/objectable_json/version.rb
|
150
|
+
- objectable_json.gemspec
|
151
|
+
homepage: https://github.com/kazuooooo/objectable-json
|
152
|
+
licenses:
|
153
|
+
- MIT
|
154
|
+
metadata: {}
|
155
|
+
post_install_message:
|
156
|
+
rdoc_options: []
|
157
|
+
require_paths:
|
158
|
+
- lib
|
159
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
160
|
+
requirements:
|
161
|
+
- - ">="
|
162
|
+
- !ruby/object:Gem::Version
|
163
|
+
version: '0'
|
164
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
165
|
+
requirements:
|
166
|
+
- - ">="
|
167
|
+
- !ruby/object:Gem::Version
|
168
|
+
version: '0'
|
169
|
+
requirements: []
|
170
|
+
rubyforge_project:
|
171
|
+
rubygems_version: 2.5.1
|
172
|
+
signing_key:
|
173
|
+
specification_version: 4
|
174
|
+
summary: simple and clever JSON => Object Mapper
|
175
|
+
test_files: []
|