json_parser 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 +1 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +56 -0
- data/Guardfile +13 -0
- data/LICENSE +22 -0
- data/README.md +2 -0
- data/Rakefile +7 -0
- data/json_parser.gemspec +27 -0
- data/lib/json_parser.rb +10 -0
- data/lib/json_parser/class_methods.rb +103 -0
- data/lib/json_parser/fetcher.rb +72 -0
- data/lib/json_parser/version.rb +3 -0
- data/spec/fixtures/json_parser.json +39 -0
- data/spec/lib/json_parser_spec.rb +317 -0
- data/spec/spec_helper.rb +20 -0
- data/spec/support/fixture_helpers.rb +19 -0
- metadata +147 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 099520dbb41927983f35746666f093785c9e3e4a
|
4
|
+
data.tar.gz: c6952b7b2b128a298e4e54210760a58cfb3e5238
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 4297d6a7cf28e3295ecc7a22e4573368774583970447a90803915a9334996a9755dbd07a80550f2108b7d8cf9c74d7eb821f1fa5faabc0d72f90f07d6c71c36e
|
7
|
+
data.tar.gz: 08e0851107751b1926997769d018a9c2714c68c3674bb1805aabe80b0d1c37a318e4d39d3145e59edafd04c77838ec06d3b9f8ec2c6cc08710db99ff17df7835
|
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
coverage
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
GIT
|
2
|
+
remote: git@github.com:Bidu/safe_attribute_assignment.git
|
3
|
+
revision: 7ccb0c0f56a1c5f8d3f844144d7b4148069bc2a0
|
4
|
+
specs:
|
5
|
+
safe_attribute_assignment (0.0.3)
|
6
|
+
activesupport
|
7
|
+
|
8
|
+
PATH
|
9
|
+
remote: .
|
10
|
+
specs:
|
11
|
+
json_parser (0.1.0)
|
12
|
+
activesupport
|
13
|
+
|
14
|
+
GEM
|
15
|
+
remote: https://rubygems.org/
|
16
|
+
specs:
|
17
|
+
activesupport (4.2.1)
|
18
|
+
i18n (~> 0.7)
|
19
|
+
json (~> 1.7, >= 1.7.7)
|
20
|
+
minitest (~> 5.1)
|
21
|
+
thread_safe (~> 0.3, >= 0.3.4)
|
22
|
+
tzinfo (~> 1.1)
|
23
|
+
diff-lcs (1.2.5)
|
24
|
+
docile (1.1.5)
|
25
|
+
i18n (0.7.0)
|
26
|
+
json (1.8.2)
|
27
|
+
minitest (5.5.1)
|
28
|
+
multi_json (1.10.1)
|
29
|
+
rake (10.4.2)
|
30
|
+
rspec (2.99.0)
|
31
|
+
rspec-core (~> 2.99.0)
|
32
|
+
rspec-expectations (~> 2.99.0)
|
33
|
+
rspec-mocks (~> 2.99.0)
|
34
|
+
rspec-core (2.99.2)
|
35
|
+
rspec-expectations (2.99.2)
|
36
|
+
diff-lcs (>= 1.1.3, < 2.0)
|
37
|
+
rspec-mocks (2.99.3)
|
38
|
+
simplecov (0.9.1)
|
39
|
+
docile (~> 1.1.0)
|
40
|
+
multi_json (~> 1.0)
|
41
|
+
simplecov-html (~> 0.8.0)
|
42
|
+
simplecov-html (0.8.0)
|
43
|
+
thread_safe (0.3.5)
|
44
|
+
tzinfo (1.2.2)
|
45
|
+
thread_safe (~> 0.1)
|
46
|
+
|
47
|
+
PLATFORMS
|
48
|
+
ruby
|
49
|
+
|
50
|
+
DEPENDENCIES
|
51
|
+
bundler (~> 1.6)
|
52
|
+
json_parser!
|
53
|
+
rake
|
54
|
+
rspec (~> 2.14)
|
55
|
+
safe_attribute_assignment (= 0.0.3)!
|
56
|
+
simplecov
|
data/Guardfile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# More info at https://github.com/guard/guard#readme
|
2
|
+
|
3
|
+
guard 'bundler' do
|
4
|
+
watch('Gemfile')
|
5
|
+
watch(/^.+\.gemspec/)
|
6
|
+
end
|
7
|
+
|
8
|
+
guard :rspec, all_after_pass: true, all_on_start: true do
|
9
|
+
watch(%r{^spec/.+_spec\.rb$})
|
10
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
11
|
+
watch('spec/spec_helper.rb') { "spec" }
|
12
|
+
end
|
13
|
+
|
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2015 Bidu.com.br
|
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 all
|
13
|
+
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 THE
|
21
|
+
SOFTWARE.
|
22
|
+
|
data/README.md
ADDED
data/Rakefile
ADDED
data/json_parser.gemspec
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'json_parser/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "json_parser"
|
8
|
+
spec.version = JsonParser::VERSION
|
9
|
+
spec.authors = ["Bidu Dev's Team"]
|
10
|
+
spec.email = ["dev@bidu.com.br"]
|
11
|
+
spec.summary = "Json Parser"
|
12
|
+
spec.description = spec.description
|
13
|
+
spec.homepage = "https://github.com/Bidu/json_parser"
|
14
|
+
|
15
|
+
spec.files = `git ls-files`.split($/)
|
16
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
17
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
|
+
spec.require_paths = ["lib"]
|
19
|
+
|
20
|
+
spec.add_runtime_dependency 'activesupport'
|
21
|
+
|
22
|
+
spec.add_development_dependency 'safe_attribute_assignment'
|
23
|
+
spec.add_development_dependency "bundler", "~> 1.6"
|
24
|
+
spec.add_development_dependency "rake"
|
25
|
+
spec.add_development_dependency "rspec", "~> 2.14"
|
26
|
+
spec.add_development_dependency 'simplecov'
|
27
|
+
end
|
data/lib/json_parser.rb
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
module JsonParser::ClassMethods
|
2
|
+
def json_parse(*attr_names)
|
3
|
+
options = {
|
4
|
+
path: nil,
|
5
|
+
json: :json,
|
6
|
+
full_path: nil,
|
7
|
+
cached: false,
|
8
|
+
class: nil,
|
9
|
+
compact: false,
|
10
|
+
after: nil,
|
11
|
+
case: :lower_camel
|
12
|
+
}.merge(attr_names.extract_options!)
|
13
|
+
|
14
|
+
builder = Builder.new(attr_names, self, options)
|
15
|
+
builder.build
|
16
|
+
end
|
17
|
+
|
18
|
+
class Builder
|
19
|
+
attr_reader :attr_names, :options, :methods_def
|
20
|
+
|
21
|
+
def initialize(attr_names, instance, options)
|
22
|
+
@attr_names = attr_names
|
23
|
+
@instance = instance
|
24
|
+
@options = options
|
25
|
+
@methods_def = []
|
26
|
+
init
|
27
|
+
end
|
28
|
+
|
29
|
+
def build
|
30
|
+
methods_def.each do |method_def|
|
31
|
+
@instance.module_eval(method_def, __FILE__, __LINE__ + 1)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def init
|
38
|
+
attr_names.each do |attr|
|
39
|
+
add_attr(attr)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def path
|
44
|
+
options[:path]
|
45
|
+
end
|
46
|
+
|
47
|
+
def json_name
|
48
|
+
options[:json]
|
49
|
+
end
|
50
|
+
|
51
|
+
def full_path(attribute)
|
52
|
+
options[:full_path] || [path, attribute].compact.join('.')
|
53
|
+
end
|
54
|
+
|
55
|
+
def cached
|
56
|
+
options[:cached]
|
57
|
+
end
|
58
|
+
|
59
|
+
def clazz
|
60
|
+
options[:class]
|
61
|
+
end
|
62
|
+
|
63
|
+
def compact
|
64
|
+
options[:compact]
|
65
|
+
end
|
66
|
+
|
67
|
+
def after
|
68
|
+
options[:after] ? ":#{options[:after]}" : false
|
69
|
+
end
|
70
|
+
|
71
|
+
def case_type
|
72
|
+
options[:case]
|
73
|
+
end
|
74
|
+
|
75
|
+
def add_attr(attribute)
|
76
|
+
@methods_def << <<-CODE
|
77
|
+
def #{attribute}
|
78
|
+
#{cached ? cached_fetcher(attribute) : attr_fetcher(attribute)}
|
79
|
+
end
|
80
|
+
CODE
|
81
|
+
end
|
82
|
+
|
83
|
+
def attr_fetcher(attribute)
|
84
|
+
<<-CODE
|
85
|
+
JsonParser::Fetcher.new(
|
86
|
+
#{json_name}, '#{full_path(attribute)}', {
|
87
|
+
instance: self,
|
88
|
+
class: #{clazz || 'nil'},
|
89
|
+
compact: #{compact || 'false'},
|
90
|
+
after: #{after},
|
91
|
+
case_type: :#{case_type}
|
92
|
+
}
|
93
|
+
).fetch
|
94
|
+
CODE
|
95
|
+
end
|
96
|
+
|
97
|
+
def cached_fetcher(attribute)
|
98
|
+
<<-CODE
|
99
|
+
@#{attribute} ||= #{attr_fetcher(attribute)}
|
100
|
+
CODE
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
class JsonParser::Fetcher
|
2
|
+
attr_reader :path, :json, :options
|
3
|
+
|
4
|
+
def initialize(json, path, options = {})
|
5
|
+
@path = path.to_s.split('.')
|
6
|
+
@json = json
|
7
|
+
@options = options
|
8
|
+
end
|
9
|
+
|
10
|
+
def fetch
|
11
|
+
value = crawl(json, path)
|
12
|
+
value = instance.send(after, value) if after
|
13
|
+
value
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def crawl(json, path)
|
19
|
+
return nil if json.nil?
|
20
|
+
return wrap(json) if path.empty?
|
21
|
+
return crawl_array(json, path) if json.is_a? Array
|
22
|
+
|
23
|
+
key = change_case(path[0])
|
24
|
+
value = json.key?(key) ? json[key] : json[key.to_sym]
|
25
|
+
crawl(value, path[1,path.size])
|
26
|
+
end
|
27
|
+
|
28
|
+
def change_case(key)
|
29
|
+
case case_type
|
30
|
+
when :lower_camel
|
31
|
+
key.camelize(:lower)
|
32
|
+
when :upper_camel
|
33
|
+
key.camelize(:upper)
|
34
|
+
when :snake
|
35
|
+
key.underscore
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def crawl_array(array, path)
|
40
|
+
array.map { |j| crawl(j, path) }.tap do |a|
|
41
|
+
a.compact! if compact
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def wrap(json)
|
46
|
+
return json unless clazz
|
47
|
+
return clazz.new json unless json.is_a? Array
|
48
|
+
json.map { |v| wrap v }.tap do |j|
|
49
|
+
j.compact! if compact
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def clazz
|
54
|
+
options[:class]
|
55
|
+
end
|
56
|
+
|
57
|
+
def after
|
58
|
+
options[:after]
|
59
|
+
end
|
60
|
+
|
61
|
+
def instance
|
62
|
+
options[:instance]
|
63
|
+
end
|
64
|
+
|
65
|
+
def compact
|
66
|
+
options[:compact]
|
67
|
+
end
|
68
|
+
|
69
|
+
def case_type
|
70
|
+
options[:case_type]
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
{
|
2
|
+
"id": 100,
|
3
|
+
"user": {
|
4
|
+
"name": "usuario"
|
5
|
+
},
|
6
|
+
"age": 20,
|
7
|
+
"father": {
|
8
|
+
"name": "father full name"
|
9
|
+
},
|
10
|
+
"hasMoney": true,
|
11
|
+
"house": {
|
12
|
+
"age": 20,
|
13
|
+
"value": 1000,
|
14
|
+
"floors": 3
|
15
|
+
},
|
16
|
+
"oldHouse": {
|
17
|
+
"age": 30,
|
18
|
+
"value": 500,
|
19
|
+
"floors": 1
|
20
|
+
},
|
21
|
+
"games": [
|
22
|
+
{
|
23
|
+
"name": "zelda",
|
24
|
+
"publisher": "nintendo"
|
25
|
+
}, {
|
26
|
+
"name": "mario",
|
27
|
+
"publisher": "nintendo"
|
28
|
+
}, {
|
29
|
+
"name": "sonic",
|
30
|
+
"publisher": "sega"
|
31
|
+
}
|
32
|
+
],
|
33
|
+
"animals":[
|
34
|
+
{"race": {"species": {"name": "European squid"}}},
|
35
|
+
{"race": {"species": {"name": "Macaque monkey"}}},
|
36
|
+
{"race": {"species": {"name": "Mexican redknee tarantula"}}}
|
37
|
+
]
|
38
|
+
|
39
|
+
}
|
@@ -0,0 +1,317 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe JsonParser do
|
4
|
+
class JsonParser::House
|
5
|
+
include JsonParser
|
6
|
+
include ::SafeAttributeAssignment
|
7
|
+
attr_reader :json
|
8
|
+
|
9
|
+
json_parse :age, :value, :floors
|
10
|
+
|
11
|
+
def initialize(json)
|
12
|
+
@json = json
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class JsonParser::Game
|
17
|
+
include JsonParser
|
18
|
+
include SafeAttributeAssignment
|
19
|
+
attr_reader :json
|
20
|
+
|
21
|
+
json_parse :name, :publisher
|
22
|
+
|
23
|
+
def initialize(json)
|
24
|
+
@json = json
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class JsonParser::Dummy
|
29
|
+
include JsonParser
|
30
|
+
attr_reader :json
|
31
|
+
|
32
|
+
json_parse :id
|
33
|
+
json_parse :name, path: 'user'
|
34
|
+
json_parse :model, path: 'car'
|
35
|
+
json_parse :father_name, full_path: 'father.name'
|
36
|
+
json_parse :age, cached: true
|
37
|
+
json_parse :has_money
|
38
|
+
json_parse :house, class: JsonParser::House
|
39
|
+
json_parse :old_house, class: JsonParser::House, cached: true
|
40
|
+
json_parse :games, class: JsonParser::Game
|
41
|
+
json_parse :species_name, full_path: 'animals.race.species.name', compact: true
|
42
|
+
json_parse :games_filtered, class: JsonParser::Game, after: :filter_games, full_path: 'games'
|
43
|
+
|
44
|
+
def initialize(json)
|
45
|
+
@json = json
|
46
|
+
end
|
47
|
+
|
48
|
+
def filter_games(games)
|
49
|
+
games.select do |g|
|
50
|
+
g.publisher != 'sega'
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
let(:dummy) { JsonParser::Dummy.new(json) }
|
56
|
+
let(:json) { load_json_fixture_file('json_parser.json') }
|
57
|
+
let(:value) { dummy.public_send(attribute) }
|
58
|
+
|
59
|
+
context 'when parser is configured with no options' do
|
60
|
+
let(:attribute) { :id }
|
61
|
+
|
62
|
+
it 'retrieves attribute from base json' do
|
63
|
+
expect(value).to eq(json['id'])
|
64
|
+
end
|
65
|
+
|
66
|
+
context 'when calling the method twice' do
|
67
|
+
before do
|
68
|
+
dummy.public_send(attribute)
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'retrieves attribute from base json' do
|
72
|
+
expect(value).to eq(json['id'])
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
context 'when changing json value' do
|
77
|
+
let!(:old_value) { json['id'] }
|
78
|
+
before do
|
79
|
+
dummy.id
|
80
|
+
json['id'] = 200
|
81
|
+
end
|
82
|
+
it 'retrieves the new value' do
|
83
|
+
expect(value).not_to eq(old_value)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
context 'when parser is configured with a path' do
|
89
|
+
let(:attribute) { :name }
|
90
|
+
|
91
|
+
it 'retrieves attribute from base json' do
|
92
|
+
expect(value).to eq(json['user']['name'])
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
context 'parser finds a nil attribute' do
|
97
|
+
let(:attribute) { :model }
|
98
|
+
|
99
|
+
it 'returns nil' do
|
100
|
+
expect(value).to be_nil
|
101
|
+
end
|
102
|
+
|
103
|
+
it do
|
104
|
+
expect { value }.not_to raise_error
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
context 'when json is instead of empty' do
|
109
|
+
let(:json) { nil }
|
110
|
+
let(:attribute) { :model }
|
111
|
+
|
112
|
+
it 'returns nil' do
|
113
|
+
expect(value).to be_nil
|
114
|
+
end
|
115
|
+
|
116
|
+
it do
|
117
|
+
expect { value }.not_to raise_error
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
context 'when configuring full path' do
|
122
|
+
let(:attribute) { :father_name }
|
123
|
+
|
124
|
+
it 'returns nil' do
|
125
|
+
expect(value).to eq(json['father']['name'])
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
context 'when caching the value' do
|
130
|
+
let(:attribute) { :age }
|
131
|
+
let!(:old_value) { json['age'] }
|
132
|
+
before do
|
133
|
+
dummy.age
|
134
|
+
json['age'] = old_value + 100
|
135
|
+
end
|
136
|
+
|
137
|
+
it 'returns cached value' do
|
138
|
+
expect(value).to eq(old_value)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
context 'with an snake case option' do
|
143
|
+
let(:attribute) { :has_money }
|
144
|
+
|
145
|
+
it 'returns camel cased value' do
|
146
|
+
expect(value).to eq(json['hasMoney'])
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
context 'when wrapping it with a class' do
|
151
|
+
let(:attribute) { :house }
|
152
|
+
|
153
|
+
it 'returns an onject wrap' do
|
154
|
+
expect(value).to be_a(JsonParser::House)
|
155
|
+
end
|
156
|
+
|
157
|
+
it 'creates the object with the given json' do
|
158
|
+
expect(value.age).to eq(json['house']['age'])
|
159
|
+
expect(value.value).to eq(json['house']['value'])
|
160
|
+
expect(value.floors).to eq(json['house']['floors'])
|
161
|
+
end
|
162
|
+
|
163
|
+
context 'when dealing with an array' do
|
164
|
+
let(:attribute) { :games }
|
165
|
+
|
166
|
+
it 'returns an array of json wrapped' do
|
167
|
+
expect(value).to be_a(Array)
|
168
|
+
value.each do |object|
|
169
|
+
expect(object).to be_a(JsonParser::Game)
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
context 'when dealing with multiple level arrays' do
|
174
|
+
let(:attribute) { :games }
|
175
|
+
before do
|
176
|
+
json['games'].map! { |j| [j] }
|
177
|
+
end
|
178
|
+
|
179
|
+
it 'returns an array of json wrapped' do
|
180
|
+
expect(value).to be_a(Array)
|
181
|
+
value.each do |object|
|
182
|
+
expect(object).to be_a(Array)
|
183
|
+
object.each do |game|
|
184
|
+
expect(game).to be_a(JsonParser::Game)
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
context 'when wrapping it with a class and caching' do
|
193
|
+
let(:attribute) { :old_house }
|
194
|
+
let!(:old_value) { json['oldHouse'] }
|
195
|
+
before do
|
196
|
+
dummy.old_house
|
197
|
+
json['oldHouse'] = {}
|
198
|
+
end
|
199
|
+
|
200
|
+
it 'returns an onject wrap' do
|
201
|
+
expect(value).to be_a(JsonParser::House)
|
202
|
+
end
|
203
|
+
|
204
|
+
it 'creates the object with the given json' do
|
205
|
+
expect(value.age).not_to eq(json['oldHouse']['age'])
|
206
|
+
expect(value.age).to eq(old_value['age'])
|
207
|
+
expect(value.value).not_to eq(json['oldHouse']['value'])
|
208
|
+
expect(value.value).to eq(old_value['value'])
|
209
|
+
expect(value.floors).not_to eq(json['oldHouse']['floors'])
|
210
|
+
expect(value.floors).to eq(old_value['floors'])
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
context 'when dealing with json inside arrays' do
|
215
|
+
let(:attribute) { :species_name }
|
216
|
+
let(:expected) do
|
217
|
+
['European squid', 'Macaque monkey', 'Mexican redknee tarantula']
|
218
|
+
end
|
219
|
+
|
220
|
+
it do
|
221
|
+
expect(value).to be_a(Array)
|
222
|
+
end
|
223
|
+
|
224
|
+
it 'parses them mapping arrays as sub parse' do
|
225
|
+
expect(value).to eq(expected)
|
226
|
+
end
|
227
|
+
|
228
|
+
context 'when there are nil values and compact is true' do
|
229
|
+
before do
|
230
|
+
json["animals"].last['race'] = nil
|
231
|
+
end
|
232
|
+
let(:expected) do
|
233
|
+
['European squid', 'Macaque monkey']
|
234
|
+
end
|
235
|
+
|
236
|
+
it 'eliminate nil values' do
|
237
|
+
expect(value).to eq(expected)
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
context 'when passing an after filter' do
|
243
|
+
let(:attribute) { :games_filtered }
|
244
|
+
|
245
|
+
it 'applies the filter after parsing the json' do
|
246
|
+
expect(value.map(&:publisher)).not_to include('sega')
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
context 'when using a snake case' do
|
251
|
+
class JsonParser::Dummy
|
252
|
+
json_parse :snake_cased, case: :snake
|
253
|
+
end
|
254
|
+
|
255
|
+
let(:json) { { snake_cased: 'snake', snakeCased: 'Camel' }.stringify_keys }
|
256
|
+
let(:attribute) { :snake_cased }
|
257
|
+
|
258
|
+
it 'fetches from snake cased fields' do
|
259
|
+
expect(value).to eq('snake')
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
context 'when using a upper camel case' do
|
264
|
+
class JsonParser::Dummy
|
265
|
+
json_parse :upper_case, case: :upper_camel
|
266
|
+
end
|
267
|
+
|
268
|
+
let(:json) { { UpperCase: 'upper', upperCase: 'lower' }.stringify_keys }
|
269
|
+
let(:attribute) { :upper_case }
|
270
|
+
|
271
|
+
it 'fetches from upper camel cased fields' do
|
272
|
+
expect(value).to eq('upper')
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
context 'when using a symbol keys' do
|
277
|
+
let(:json) { load_json_fixture_file('json_parser.json').symbolize_keys }
|
278
|
+
let(:attribute) { :id }
|
279
|
+
|
280
|
+
it 'fetches from symbol keys' do
|
281
|
+
expect(value).to eq(json[:id])
|
282
|
+
end
|
283
|
+
|
284
|
+
context 'parser finds a nil attribute' do
|
285
|
+
let(:attribute) { :model }
|
286
|
+
|
287
|
+
it 'returns nil' do
|
288
|
+
expect(value).to be_nil
|
289
|
+
end
|
290
|
+
|
291
|
+
it do
|
292
|
+
expect { value }.not_to raise_error
|
293
|
+
end
|
294
|
+
end
|
295
|
+
end
|
296
|
+
|
297
|
+
context 'when using key with false value' do
|
298
|
+
let(:attribute) { :has_money }
|
299
|
+
before do
|
300
|
+
json['hasMoney'] = false
|
301
|
+
end
|
302
|
+
|
303
|
+
context 'with string keys' do
|
304
|
+
it { expect(value).to be_falsey }
|
305
|
+
it { expect(value).not_to be_nil }
|
306
|
+
end
|
307
|
+
|
308
|
+
context 'with symbol keys' do
|
309
|
+
before do
|
310
|
+
json.symbolize_keys!
|
311
|
+
end
|
312
|
+
|
313
|
+
it { expect(value).to be_falsey }
|
314
|
+
it { expect(value).not_to be_nil }
|
315
|
+
end
|
316
|
+
end
|
317
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'simplecov'
|
2
|
+
SimpleCov.start
|
3
|
+
|
4
|
+
require 'json_parser'
|
5
|
+
require 'safe_attribute_assignment'
|
6
|
+
|
7
|
+
support_files = File.expand_path("spec/support/**/*.rb")
|
8
|
+
Dir[support_files].each { |file| require file }
|
9
|
+
|
10
|
+
RSpec.configure do |config|
|
11
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
12
|
+
config.run_all_when_everything_filtered = true
|
13
|
+
config.filter_run :focus
|
14
|
+
config.filter_run_excluding :integration unless ENV['ALL']
|
15
|
+
|
16
|
+
config.order = 'random'
|
17
|
+
|
18
|
+
config.before do
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'active_support'
|
2
|
+
|
3
|
+
module FixtureHelpers
|
4
|
+
def load_fixture_file(filename)
|
5
|
+
File.read (['./spec/', 'fixtures', filename].join('/'))
|
6
|
+
end
|
7
|
+
|
8
|
+
def load_json_fixture_file(filename)
|
9
|
+
cached_json_fixture_file(filename)
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def cached_json_fixture_file(filename)
|
15
|
+
ActiveSupport::JSON.decode(load_fixture_file(filename))
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
RSpec.configuration.include FixtureHelpers
|
metadata
ADDED
@@ -0,0 +1,147 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: json_parser
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Bidu Dev's Team
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-05-08 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activesupport
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: safe_attribute_assignment
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: bundler
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ~>
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.6'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.6'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ~>
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '2.14'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ~>
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '2.14'
|
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'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
description: ''
|
98
|
+
email:
|
99
|
+
- dev@bidu.com.br
|
100
|
+
executables: []
|
101
|
+
extensions: []
|
102
|
+
extra_rdoc_files: []
|
103
|
+
files:
|
104
|
+
- .gitignore
|
105
|
+
- Gemfile
|
106
|
+
- Gemfile.lock
|
107
|
+
- Guardfile
|
108
|
+
- LICENSE
|
109
|
+
- README.md
|
110
|
+
- Rakefile
|
111
|
+
- json_parser.gemspec
|
112
|
+
- lib/json_parser.rb
|
113
|
+
- lib/json_parser/class_methods.rb
|
114
|
+
- lib/json_parser/fetcher.rb
|
115
|
+
- lib/json_parser/version.rb
|
116
|
+
- spec/fixtures/json_parser.json
|
117
|
+
- spec/lib/json_parser_spec.rb
|
118
|
+
- spec/spec_helper.rb
|
119
|
+
- spec/support/fixture_helpers.rb
|
120
|
+
homepage: https://github.com/Bidu/json_parser
|
121
|
+
licenses: []
|
122
|
+
metadata: {}
|
123
|
+
post_install_message:
|
124
|
+
rdoc_options: []
|
125
|
+
require_paths:
|
126
|
+
- lib
|
127
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - '>='
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
133
|
+
requirements:
|
134
|
+
- - '>='
|
135
|
+
- !ruby/object:Gem::Version
|
136
|
+
version: '0'
|
137
|
+
requirements: []
|
138
|
+
rubyforge_project:
|
139
|
+
rubygems_version: 2.2.2
|
140
|
+
signing_key:
|
141
|
+
specification_version: 4
|
142
|
+
summary: Json Parser
|
143
|
+
test_files:
|
144
|
+
- spec/fixtures/json_parser.json
|
145
|
+
- spec/lib/json_parser_spec.rb
|
146
|
+
- spec/spec_helper.rb
|
147
|
+
- spec/support/fixture_helpers.rb
|