json_resource 1.0.0 → 1.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/README.md +65 -0
- data/lib/json_resource/model.rb +32 -7
- data/lib/json_resource/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9c5d0ad6feca66b6bd7524037d69edf9da40ba45c5f25a6441ef4543d174e5ad
|
4
|
+
data.tar.gz: 6ee0efc65381f5243b3da05ef710dc7a8ea6e296708e2a4224c680b728fb9331
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f534f05c6e7748186cfb3373c3b55c5891d0c572be08b917f380d4cf49443a60dbdda258a3dda9778edd9b623eb4f4d45cff2c5223423c8ad450cacfde050030
|
7
|
+
data.tar.gz: 0f7703523f9b619ce117fb889fd6f9eba4738a6ceeed9d5e043edc54c1c057f25ba4d788da958b2a7121ddd93a5688787477618f0a247ff294305b804dc89a77
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -62,3 +62,68 @@ posts.first.body => 'Lorem ipsum'
|
|
62
62
|
posts.first.status_text => 'published'
|
63
63
|
posts.first.comments.first.author => 'Mr. Spock'
|
64
64
|
```
|
65
|
+
|
66
|
+
## Instantiation
|
67
|
+
|
68
|
+
To instantiate collections, use `collection_from_json` on a JSON array.
|
69
|
+
|
70
|
+
To instantiate single objects, use `from_json` on a JSON hash.
|
71
|
+
|
72
|
+
|
73
|
+
## Field types
|
74
|
+
|
75
|
+
Attributes can have one of the following types:
|
76
|
+
|
77
|
+
| Type | Conversion | Options |
|
78
|
+
| ----------- | ------------------- | ------------------------- |
|
79
|
+
| `:string` | `value` | |
|
80
|
+
| `:integer` | `value.to_i` | |
|
81
|
+
| `:float` | `value.to_f` | |
|
82
|
+
| `:boolean` | any of `[true, 1, '1', 't', 'T', 'true', 'TRUE', 'on', 'ON']` | |
|
83
|
+
| `:decimal` | direct, or `to_d` | `:precision`, `:scale` |
|
84
|
+
| `:date` | `Date.parse` | |
|
85
|
+
| `:time` | `Time.parse` | |
|
86
|
+
|
87
|
+
|
88
|
+
## Extracting data
|
89
|
+
|
90
|
+
Sometimes, APIs return data wrapped within arrays of hashes of arrays etc:
|
91
|
+
|
92
|
+
```json
|
93
|
+
{
|
94
|
+
"data": [
|
95
|
+
{
|
96
|
+
"status": "ok"
|
97
|
+
},
|
98
|
+
{
|
99
|
+
"planets": [
|
100
|
+
{
|
101
|
+
"name": "Earth",
|
102
|
+
"mass": 5.9722E+24,
|
103
|
+
"orbit": 1.000
|
104
|
+
},
|
105
|
+
{
|
106
|
+
"name": "Jupiter",
|
107
|
+
"mass": 1.8990E+27,
|
108
|
+
"orbit": 5.205
|
109
|
+
}
|
110
|
+
]
|
111
|
+
}
|
112
|
+
]
|
113
|
+
}
|
114
|
+
```
|
115
|
+
|
116
|
+
```ruby
|
117
|
+
class Planet
|
118
|
+
include JsonResource::Model
|
119
|
+
|
120
|
+
attribute :name, type: :string
|
121
|
+
attribute :mass, type: :decimal, precision: 10, scale: 4
|
122
|
+
end
|
123
|
+
```
|
124
|
+
|
125
|
+
To dig for this data, a call-sequence can be provided as the `root` option.
|
126
|
+
|
127
|
+
```ruby
|
128
|
+
planets = Planet.collection_from_json(json, root: %w[data [1] planets])
|
129
|
+
```
|
data/lib/json_resource/model.rb
CHANGED
@@ -3,6 +3,7 @@ module JsonResource
|
|
3
3
|
|
4
4
|
module Model
|
5
5
|
TRUE_VALUES = [true, 1, '1', 't', 'T', 'true', 'TRUE', 'on', 'ON'].to_set
|
6
|
+
BIGDECIMAL_PRECISION = 18
|
6
7
|
|
7
8
|
def self.included(base)
|
8
9
|
base.extend ClassMethods
|
@@ -23,7 +24,7 @@ module JsonResource
|
|
23
24
|
if path = attribute_path(name)
|
24
25
|
value = json_dig(json, *path)
|
25
26
|
if !value.nil? && type = attribute_type(name)
|
26
|
-
value = cast_to(type, value)
|
27
|
+
value = cast_to(type, value, name)
|
27
28
|
end
|
28
29
|
attrs[name] = value
|
29
30
|
end
|
@@ -46,7 +47,7 @@ module JsonResource
|
|
46
47
|
|
47
48
|
def collection_from_json(obj, defaults: {}, root: nil)
|
48
49
|
json = parse(obj)
|
49
|
-
json = json_dig(json, root) if root
|
50
|
+
json = json_dig(json, *root) if root
|
50
51
|
json.map { |hsh| from_json(hsh, defaults: defaults) }.compact
|
51
52
|
end
|
52
53
|
|
@@ -95,16 +96,20 @@ module JsonResource
|
|
95
96
|
end
|
96
97
|
|
97
98
|
[:attribute, :object, :collection].each do |method_name|
|
99
|
+
define_method "#{method_name}_options" do |name|
|
100
|
+
send(method_name.to_s.pluralize).try(:[], name)
|
101
|
+
end
|
102
|
+
|
98
103
|
define_method "#{method_name}_path" do |name|
|
99
|
-
options = send(method_name
|
100
|
-
Array(options
|
104
|
+
options = send("#{method_name}_options", name)
|
105
|
+
Array(options.try(:[], :path)).presence || [inflect(name)]
|
101
106
|
end
|
102
107
|
end
|
103
108
|
|
104
109
|
def attribute_type(name)
|
105
110
|
attributes[name] && attributes[name][:type]
|
106
111
|
end
|
107
|
-
|
112
|
+
|
108
113
|
def object_class(name)
|
109
114
|
if objects[name] && class_name = objects[name][:class_name]
|
110
115
|
class_name.constantize
|
@@ -121,13 +126,13 @@ module JsonResource
|
|
121
126
|
end
|
122
127
|
end
|
123
128
|
|
124
|
-
def cast_to(type, value) # only called for non-nil values
|
129
|
+
def cast_to(type, value, name) # only called for non-nil values
|
125
130
|
case type
|
126
131
|
when :string then value
|
127
132
|
when :integer then value.to_i
|
128
133
|
when :float then value.to_f
|
129
134
|
when :boolean then cast_to_boolean(value)
|
130
|
-
when :decimal then
|
135
|
+
when :decimal then cast_to_big_decimal(value, **attribute_options(name))
|
131
136
|
when :date then value.presence && Date.parse(value)
|
132
137
|
when :time then value.presence && Time.parse(value)
|
133
138
|
else
|
@@ -142,6 +147,26 @@ module JsonResource
|
|
142
147
|
TRUE_VALUES.include?(value)
|
143
148
|
end
|
144
149
|
end
|
150
|
+
|
151
|
+
def cast_to_big_decimal(value, scale: nil, precision: nil, **)
|
152
|
+
cast_value = case value
|
153
|
+
when ::Float
|
154
|
+
precision ||= BIGDECIMAL_PRECISION
|
155
|
+
float_precision = precision.to_i > ::Float::DIG + 1 ? ::Float::DIG + 1 : precision.to_i
|
156
|
+
BigDecimal(value, float_precision)
|
157
|
+
when ::Numeric
|
158
|
+
BigDecimal(value, precision || BIGDECIMAL_PRECISION)
|
159
|
+
when ::String
|
160
|
+
begin
|
161
|
+
value.to_d
|
162
|
+
rescue ArgumentError
|
163
|
+
BigDecimal(0)
|
164
|
+
end
|
165
|
+
else
|
166
|
+
value.respond_to?(:to_d) ? value.to_d : BigDecimal(value.to_s)
|
167
|
+
end
|
168
|
+
scale ? cast_value.round(scale) : cast_value
|
169
|
+
end
|
145
170
|
|
146
171
|
def parse(obj)
|
147
172
|
case obj
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: json_resource
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matthias Grosser
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-11-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: json
|
@@ -52,7 +52,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
52
52
|
requirements:
|
53
53
|
- - ">="
|
54
54
|
- !ruby/object:Gem::Version
|
55
|
-
version: 2.
|
55
|
+
version: 2.7.0
|
56
56
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
57
57
|
requirements:
|
58
58
|
- - ">="
|