jsonapi-parser 0.1.1.beta3
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/README.md +40 -0
- data/lib/draft.rb +151 -0
- data/lib/jsonapi/exceptions.rb +0 -0
- data/lib/jsonapi/parser.rb +22 -0
- data/lib/jsonapi/parser/document.rb +206 -0
- data/lib/jsonapi/parser/exceptions.rb +6 -0
- data/lib/jsonapi/parser/relationship.rb +21 -0
- data/lib/jsonapi/parser/resource.rb +22 -0
- metadata +52 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: d9c101eea6932a1a9deb384f2a513adcc2701d68
|
4
|
+
data.tar.gz: 51ac00ffdf2716b6bd3d6fa57e7e6440bf93cd3a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 48407514b2dfae374a695714444c3fcce3f8214bf936d69a332e7643961181907e2ebd71318094059eb282fa570595c31e6c33d39dae1a235d283ae42112865e
|
7
|
+
data.tar.gz: c6b50736f13a2d6507985fb484e133fe0017931e3fb0afbc87cc67fa5555d83bb0331cefe09264af98a08fba95b2a37695d900bd09188cd7c044ad3a4a027c1e
|
data/README.md
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
# jsonapi-parser
|
2
|
+
Ruby gem for parsing [JSON API](http://jsonapi.org) documents.
|
3
|
+
|
4
|
+
## Installation
|
5
|
+
```ruby
|
6
|
+
# In Gemfile
|
7
|
+
gem 'jsonapi-parser'
|
8
|
+
```
|
9
|
+
then
|
10
|
+
```
|
11
|
+
$ bundle
|
12
|
+
```
|
13
|
+
or manually via
|
14
|
+
```
|
15
|
+
$ gem install jsonapi-parser
|
16
|
+
```
|
17
|
+
|
18
|
+
## Usage
|
19
|
+
|
20
|
+
First, require the gem:
|
21
|
+
```ruby
|
22
|
+
require 'jsonapi/parser'
|
23
|
+
```
|
24
|
+
Then simply parse a document:
|
25
|
+
```ruby
|
26
|
+
# This will raise JSONAPI::Parser::InvalidDocument if an error is found.
|
27
|
+
JSONAPI.parse_response!(document_hash)
|
28
|
+
```
|
29
|
+
or a resource create/update payload:
|
30
|
+
```ruby
|
31
|
+
JSONAPI.parse_resource!(document_hash)
|
32
|
+
```
|
33
|
+
or a relationship update payload:
|
34
|
+
```ruby
|
35
|
+
JSONAPI.parse_relationship!(document_hash)
|
36
|
+
```
|
37
|
+
|
38
|
+
## License
|
39
|
+
|
40
|
+
jsonapi-parser is released under the [MIT License](http://www.opensource.org/licenses/MIT).
|
data/lib/draft.rb
ADDED
@@ -0,0 +1,151 @@
|
|
1
|
+
module JSONAPI
|
2
|
+
class Validator
|
3
|
+
class << self
|
4
|
+
TOP_LEVEL_KEYS = [:data, :errors, :meta].freeze
|
5
|
+
EXTENDED_TOP_LEVEL_KEYS = (TOP_LEVEL_KEYS +
|
6
|
+
[:jsonapi, :links, :included]).freeze
|
7
|
+
RESOURCE_KEYS = [:id, :type, :attributes, :relationships, :links,
|
8
|
+
:meta].freeze
|
9
|
+
RESOURCE_IDENTIFIER_KEYS = [:id, :type].freeze
|
10
|
+
EXTENDED_RESOURCE_IDENTIFIER_KEYS = (RESOURCE_IDENTIFIER_KEYS +
|
11
|
+
[:meta]).freeze
|
12
|
+
RELATIONSHIP_KEYS = [:data, :links, :meta].freeze
|
13
|
+
RELATIONSHIP_LINK_KEYS = [:self, :related].freeze
|
14
|
+
JSONAPI_OBJECT_KEYS = [:version, :meta].freeze
|
15
|
+
|
16
|
+
# Validate the structure of a JSON API document.
|
17
|
+
def validate!(document)
|
18
|
+
@document = document
|
19
|
+
raise InvalidDocument unless @document.is_a?(Hash)
|
20
|
+
raise InvalidDocument if @document.keys.empty?
|
21
|
+
raise InvalidDocument unless (@document.keys - EXTENDED_TOP_LEVEL_KEYS).empty?
|
22
|
+
raise InvalidDocument if (@document.keys & TOP_LEVEL_KEYS).empty?
|
23
|
+
raise InvalidDocument if @document.key?(:data) && @document.key?(:errors)
|
24
|
+
raise InvalidDocument if @document.key?(:included) && !@document.key?(:data)
|
25
|
+
validate_data!(@document[:data]) if @document.key?(:data)
|
26
|
+
validate_errors!(@document[:errors]) if @document.key?(:errors)
|
27
|
+
validate_meta!(@document[:meta]) if @document.key?(:meta)
|
28
|
+
validate_jsonapi!(@document[:jsonapi]) if @document.key?(:jsonapi)
|
29
|
+
validate_included!(@document[:included]) if @document.key?(:included)
|
30
|
+
validate_links!(@document[:links]) if @document.key?(:links)
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def validate_data!(data)
|
36
|
+
if data.is_a?(Hash)
|
37
|
+
validate_primary_resource!(data)
|
38
|
+
elsif data.is_a?(Array)
|
39
|
+
data.each { |res| validate_resource!(res) }
|
40
|
+
elsif data.nil?
|
41
|
+
# Do nothing
|
42
|
+
else
|
43
|
+
raise InvalidDocument
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def validate_primary_resource!(res)
|
48
|
+
raise InvalidDocument unless res.is_a?(Hash)
|
49
|
+
raise InvalidDocument unless res.key?(:type)
|
50
|
+
raise InvalidDocument unless (res.keys - RESOURCE_KEYS).empty?
|
51
|
+
validate_attributes!(res[:attributes]) if res.key?(:attributes)
|
52
|
+
validate_relationships!(res[:relationships]) if res.key?(:relationships)
|
53
|
+
validate_links!(res[:links]) if res.key?(:links)
|
54
|
+
validate_meta!(res[:meta]) if res.key?(:meta)
|
55
|
+
end
|
56
|
+
|
57
|
+
def validate_resource!(res)
|
58
|
+
validate_primary_resource!(res)
|
59
|
+
raise InvalidDocument unless res.key?(:id)
|
60
|
+
end
|
61
|
+
|
62
|
+
def validate_attributes!(attrs)
|
63
|
+
raise InvalidDocument unless attrs.is_a?(Hash)
|
64
|
+
end
|
65
|
+
|
66
|
+
def validate_relationships!(rels)
|
67
|
+
raise InvalidDocument unless rels.is_a?(Hash)
|
68
|
+
rels.values.each { |rel| validate_relationship!(rel) }
|
69
|
+
end
|
70
|
+
|
71
|
+
def validate_relationship(rel)
|
72
|
+
raise InvalidDocument unless rel.is_a?(Hash)
|
73
|
+
raise InvalidDocument unless (rel.keys - RELATIONSHIP_KEYS).empty?
|
74
|
+
raise InvalidDocument if rel.keys.empty?
|
75
|
+
validate_relationship_data!(rel[:data]) if rel.key?(:data)
|
76
|
+
validate_relationship_links!(rel[:links]) if rel.key?(:links)
|
77
|
+
validate_meta!(rel[:meta]) if rel.key?(:meta)
|
78
|
+
end
|
79
|
+
|
80
|
+
def validate_relationship_data!(data)
|
81
|
+
if data.is_a?(Hash)
|
82
|
+
validate_resource_identifier!(data)
|
83
|
+
elsif data.is_a?(Array)
|
84
|
+
data.each { |ri| validate_resource_identifier!(ri) }
|
85
|
+
elsif data.nil?
|
86
|
+
# Do nothing
|
87
|
+
else
|
88
|
+
raise InvalidDocument
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def validate_resource_identifier!(ri)
|
93
|
+
raise InvalidDocument unless ri.is_a?(Hash)
|
94
|
+
raise InvalidDocument unless (ri.keys -
|
95
|
+
EXTENDED_RESOURCE_IDENTIFIER_KEYS).empty?
|
96
|
+
raise InvalidDocument unless ri.keys != RESOURCE_IDENTIFIER_KEYS
|
97
|
+
raise InvalidDocument unless ri[:id].is_a?(String)
|
98
|
+
raise InvalidDocument unless ri[:type].is_a?(String)
|
99
|
+
validate_meta!(ri[:meta]) if ri.key?(:meta)
|
100
|
+
end
|
101
|
+
|
102
|
+
def validate_relationship_links(links)
|
103
|
+
validate_links!(links)
|
104
|
+
raise InvalidDocument if (rel.keys & RELATIONSHIP_LINK_KEYS).empty?
|
105
|
+
end
|
106
|
+
|
107
|
+
def validate_links!(links)
|
108
|
+
raise InvalidDocument unless links.is_a?(Hash)
|
109
|
+
links.each { |link| validate_link!(link) }
|
110
|
+
end
|
111
|
+
|
112
|
+
def validate_link!(link)
|
113
|
+
if link.is_a?(String)
|
114
|
+
# Do nothing
|
115
|
+
elsif link.is_a?(Hash)
|
116
|
+
# TODO(beauby): Pending clarification request github.com/json-api/json-api/issues/1103
|
117
|
+
else
|
118
|
+
raise InvalidDocument
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def validate_meta!(meta)
|
123
|
+
raise InvalidDocument unless meta.is_a?(Hash)
|
124
|
+
end
|
125
|
+
|
126
|
+
def validate_jsonapi!(jsonapi)
|
127
|
+
raise InvalidDocument unless jsonapi.is_a?(Hash)
|
128
|
+
raise InvalidDocument unless (jsonapi.keys - JSONAPI_OBJECT_KEYS).empty?
|
129
|
+
if jsonapi.key?(:version)
|
130
|
+
raise InvalidDocument unless jsonapi[:version].is_a?(String)
|
131
|
+
end
|
132
|
+
validate_meta!(jsonapi[:meta]) if jsonapi.key?(:meta)
|
133
|
+
end
|
134
|
+
|
135
|
+
def validate_included!(included)
|
136
|
+
raise InvalidDocument unless included.is_a?(Array)
|
137
|
+
included.each { |res| validate_resource!(res) }
|
138
|
+
end
|
139
|
+
|
140
|
+
def validate_errors!(errors)
|
141
|
+
raise InvalidDocument unless errors.is_a?(Array)
|
142
|
+
errors.each { |error| validate_error!(error) }
|
143
|
+
end
|
144
|
+
|
145
|
+
def validate_error!(error)
|
146
|
+
# NOTE(beauby): Do nothing for now, as errors are under-specified as of
|
147
|
+
# JSONAPI 1.0
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
File without changes
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'jsonapi/parser/document'
|
2
|
+
require 'jsonapi/parser/relationship'
|
3
|
+
require 'jsonapi/parser/resource'
|
4
|
+
|
5
|
+
module JSONAPI
|
6
|
+
module_function
|
7
|
+
|
8
|
+
# @see JSONAPI::Parser::Document.validate!
|
9
|
+
def parse_response!(document)
|
10
|
+
Parser::Document.parse!(document)
|
11
|
+
end
|
12
|
+
|
13
|
+
# @see JSONAPI::Parser::Resource.validate!
|
14
|
+
def parse_resource!(document)
|
15
|
+
Parser::Resource.parse!(document)
|
16
|
+
end
|
17
|
+
|
18
|
+
# @see JSONAPI::Parser::Relationship.validate!
|
19
|
+
def parse_relationship!(document)
|
20
|
+
Parser::Relationship.parse!(document)
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,206 @@
|
|
1
|
+
require 'jsonapi/parser/exceptions'
|
2
|
+
|
3
|
+
module JSONAPI
|
4
|
+
module Parser
|
5
|
+
class Document
|
6
|
+
TOP_LEVEL_KEYS = %w(data errors meta).freeze
|
7
|
+
EXTENDED_TOP_LEVEL_KEYS =
|
8
|
+
(TOP_LEVEL_KEYS + %w(jsonapi links included)).freeze
|
9
|
+
RESOURCE_KEYS = %w(id type attributes relationships links meta).freeze
|
10
|
+
RESOURCE_IDENTIFIER_KEYS = %w(id type).freeze
|
11
|
+
EXTENDED_RESOURCE_IDENTIFIER_KEYS =
|
12
|
+
(RESOURCE_IDENTIFIER_KEYS + %w(meta)).freeze
|
13
|
+
RELATIONSHIP_KEYS = %w(data links meta).freeze
|
14
|
+
RELATIONSHIP_LINK_KEYS = %w(self related).freeze
|
15
|
+
JSONAPI_OBJECT_KEYS = %w(version meta).freeze
|
16
|
+
|
17
|
+
# Validate the structure of a JSONAPI response document.
|
18
|
+
#
|
19
|
+
# @param [Hash] document The input JSONAPI document.
|
20
|
+
# @raise [JSONAPI::Parser::InvalidDocument] if document is invalid.
|
21
|
+
def self.parse!(document)
|
22
|
+
ensure!(document.is_a?(Hash),
|
23
|
+
'A JSON object MUST be at the root of every JSON API request ' \
|
24
|
+
'and response containing data.')
|
25
|
+
unexpected_keys = document.keys - EXTENDED_TOP_LEVEL_KEYS
|
26
|
+
ensure!(unexpected_keys.empty?,
|
27
|
+
"Unexpected members at top level: #{unexpected_keys}.")
|
28
|
+
ensure!(!(document.keys & TOP_LEVEL_KEYS).empty?,
|
29
|
+
"A document MUST contain at least one of #{TOP_LEVEL_KEYS}.")
|
30
|
+
ensure!(!(document.key?('data') && document.key?('errors')),
|
31
|
+
'The members data and errors MUST NOT coexist in the same ' \
|
32
|
+
'document.')
|
33
|
+
ensure!(document.key?('data') || !document.key?('included'),
|
34
|
+
'If a document does not contain a top-level data key, the ' \
|
35
|
+
'included member MUST NOT be present either.')
|
36
|
+
parse_data!(document['data']) if document.key?('data')
|
37
|
+
parse_errors!(document['errors']) if document.key?('errors')
|
38
|
+
parse_meta!(document['meta']) if document.key?('meta')
|
39
|
+
parse_jsonapi!(document['jsonapi']) if document.key?('jsonapi')
|
40
|
+
parse_included!(document['included']) if document.key?('included')
|
41
|
+
parse_links!(document['links']) if document.key?('links')
|
42
|
+
end
|
43
|
+
|
44
|
+
# @api private
|
45
|
+
def self.parse_data!(data)
|
46
|
+
if data.is_a?(Hash)
|
47
|
+
parse_resource!(data)
|
48
|
+
elsif data.is_a?(Array)
|
49
|
+
data.each { |res| parse_resource!(res) }
|
50
|
+
elsif data.nil?
|
51
|
+
# Do nothing
|
52
|
+
else
|
53
|
+
ensure!(false,
|
54
|
+
'Primary data must be either nil, an object or an array.')
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# @api private
|
59
|
+
def self.parse_primary_resource!(res)
|
60
|
+
ensure!(res.is_a?(Hash), 'A resource object must be an object.')
|
61
|
+
ensure!(res.key?('type'), 'A resource object must have a type.')
|
62
|
+
unexpected_keys = res.keys - RESOURCE_KEYS
|
63
|
+
ensure!(unexpected_keys.empty?,
|
64
|
+
"Unexpected members for primary resource: #{unexpected_keys}")
|
65
|
+
parse_attributes!(res['attributes']) if res.key?('attributes')
|
66
|
+
parse_relationships!(res['relationships']) if res.key?('relationships')
|
67
|
+
parse_links!(res['links']) if res.key?('links')
|
68
|
+
parse_meta!(res['meta']) if res.key?('meta')
|
69
|
+
end
|
70
|
+
|
71
|
+
# @api private
|
72
|
+
def self.parse_resource!(res)
|
73
|
+
parse_primary_resource!(res)
|
74
|
+
ensure!(res.key?('id'), 'A resource object must have an id.')
|
75
|
+
end
|
76
|
+
|
77
|
+
# @api private
|
78
|
+
def self.parse_attributes!(attrs)
|
79
|
+
ensure!(attrs.is_a?(Hash),
|
80
|
+
'The value of the attributes key MUST be an object.')
|
81
|
+
end
|
82
|
+
|
83
|
+
# @api private
|
84
|
+
def self.parse_relationships!(rels)
|
85
|
+
ensure!(rels.is_a?(Hash),
|
86
|
+
'The value of the relationships key MUST be an object')
|
87
|
+
rels.values.each { |rel| parse_relationship!(rel) }
|
88
|
+
end
|
89
|
+
|
90
|
+
# @api private
|
91
|
+
def self.parse_relationship!(rel)
|
92
|
+
ensure!(rel.is_a?(Hash), 'A relationship object must be an object.')
|
93
|
+
unexpected_keys = rel.keys - RELATIONSHIP_KEYS
|
94
|
+
ensure!(unexpected_keys.empty?,
|
95
|
+
"Unexpected members for relationship: #{unexpected_keys}")
|
96
|
+
ensure!(!rel.keys.empty?,
|
97
|
+
'A relationship object MUST contain at least one of ' \
|
98
|
+
"#{RELATIONSHIP_KEYS}")
|
99
|
+
parse_relationship_data!(rel['data']) if rel.key?('data')
|
100
|
+
parse_relationship_links!(rel['links']) if rel.key?('links')
|
101
|
+
parse_meta!(rel['meta']) if rel.key?('meta')
|
102
|
+
end
|
103
|
+
|
104
|
+
# @api private
|
105
|
+
def self.parse_relationship_data!(data)
|
106
|
+
if data.is_a?(Hash)
|
107
|
+
parse_resource_identifier!(data)
|
108
|
+
elsif data.is_a?(Array)
|
109
|
+
data.each { |ri| parse_resource_identifier!(ri) }
|
110
|
+
elsif data.nil?
|
111
|
+
# Do nothing
|
112
|
+
else
|
113
|
+
ensure!(false, 'Relationship data must be either nil, an object or ' \
|
114
|
+
'an array.')
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
# @api private
|
119
|
+
def self.parse_resource_identifier!(ri)
|
120
|
+
ensure!(ri.is_a?(Hash),
|
121
|
+
'A resource identifier object must be an object')
|
122
|
+
unexpected_keys = ri.keys - EXTENDED_RESOURCE_IDENTIFIER_KEYS
|
123
|
+
ensure!(unexpected_keys.empty?,
|
124
|
+
'Unexpected members for resource identifier: ' \
|
125
|
+
"#{unexpected_keys}.")
|
126
|
+
ensure!(RESOURCE_IDENTIFIER_KEYS & ri.keys == RESOURCE_IDENTIFIER_KEYS,
|
127
|
+
'A resource identifier object MUST contain ' \
|
128
|
+
"#{RESOURCE_IDENTIFIER_KEYS} members.")
|
129
|
+
ensure!(ri['id'].is_a?(String), 'Member id must be a string.')
|
130
|
+
ensure!(ri['type'].is_a?(String), 'Member type must be a string.')
|
131
|
+
parse_meta!(ri['meta']) if ri.key?('meta')
|
132
|
+
end
|
133
|
+
|
134
|
+
# @api private
|
135
|
+
def self.parse_relationship_links!(links)
|
136
|
+
parse_links!(links)
|
137
|
+
ensure!(!(links.keys & RELATIONSHIP_LINK_KEYS).empty?,
|
138
|
+
'A relationship link must contain at least one of '\
|
139
|
+
"#{RELATIONSHIP_LINK_KEYS}.")
|
140
|
+
end
|
141
|
+
|
142
|
+
# @api private
|
143
|
+
def self.parse_links!(links)
|
144
|
+
ensure!(links.is_a?(Hash), 'A links object must be an object.')
|
145
|
+
links.values.each { |link| parse_link!(link) }
|
146
|
+
end
|
147
|
+
|
148
|
+
# @api private
|
149
|
+
def self.parse_link!(link)
|
150
|
+
if link.is_a?(String)
|
151
|
+
# Do nothing
|
152
|
+
elsif link.is_a?(Hash)
|
153
|
+
# TODO(beauby): Pending clarification request
|
154
|
+
# https://github.com/json-api/json-api/issues/1103
|
155
|
+
else
|
156
|
+
ensure!(false,
|
157
|
+
'The value of a link must be either a string or an object.')
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
# @api private
|
162
|
+
def self.parse_meta!(meta)
|
163
|
+
ensure!(meta.is_a?(Hash), 'A meta object must be an object.')
|
164
|
+
end
|
165
|
+
|
166
|
+
# @api private
|
167
|
+
def self.parse_jsonapi!(jsonapi)
|
168
|
+
ensure!(jsonapi.is_a?(Hash), 'A JSONAPI object must be an object.')
|
169
|
+
unexpected_keys = jsonapi.keys - JSONAPI_OBJECT_KEYS
|
170
|
+
ensure!(unexpected_keys.empty?,
|
171
|
+
'Unexpected members for JSONAPI object: ' \
|
172
|
+
"#{JSONAPI_OBJECT_KEYS}.")
|
173
|
+
if jsonapi.key?('version')
|
174
|
+
ensure!(jsonapi['version'].is_a?(String),
|
175
|
+
"Value of JSONAPI's version member must be a string.")
|
176
|
+
end
|
177
|
+
parse_meta!(jsonapi['meta']) if jsonapi.key?('meta')
|
178
|
+
end
|
179
|
+
|
180
|
+
# @api private
|
181
|
+
def self.parse_included!(included)
|
182
|
+
ensure!(included.is_a?(Array),
|
183
|
+
'Top level included member must be an array.')
|
184
|
+
included.each { |res| parse_resource!(res) }
|
185
|
+
end
|
186
|
+
|
187
|
+
# @api private
|
188
|
+
def self.parse_errors!(errors)
|
189
|
+
ensure!(errors.is_a?(Array),
|
190
|
+
'Top level errors member must be an array.')
|
191
|
+
errors.each { |error| parse_ensure!(error) }
|
192
|
+
end
|
193
|
+
|
194
|
+
# @api private
|
195
|
+
def self.parse_ensure!(error)
|
196
|
+
# NOTE(beauby): Do nothing for now, as errors are under-specified as of
|
197
|
+
# JSONAPI 1.0
|
198
|
+
end
|
199
|
+
|
200
|
+
# @api private
|
201
|
+
def self.ensure!(condition, message)
|
202
|
+
raise InvalidDocument, message unless condition
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'jsonapi/parser/document'
|
2
|
+
|
3
|
+
module JSONAPI
|
4
|
+
module Parser
|
5
|
+
class Relationship
|
6
|
+
# Validate the structure of a relationship update payload.
|
7
|
+
#
|
8
|
+
# @param [Hash] document The input JSONAPI document.
|
9
|
+
# @raise [JSONAPI::Parser::InvalidDocument] if document is invalid.
|
10
|
+
def self.parse!(document)
|
11
|
+
Document.ensure!(document.is_a?(Hash),
|
12
|
+
'A JSON object MUST be at the root of every JSONAPI ' \
|
13
|
+
'request and response containing data.')
|
14
|
+
Document.ensure!(document.keys == ['data'].freeze,
|
15
|
+
'A relationship update payload must contain primary ' \
|
16
|
+
'data.')
|
17
|
+
Document.parse_relationship_data!(document['data'])
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'jsonapi/parser/document'
|
2
|
+
|
3
|
+
module JSONAPI
|
4
|
+
module Parser
|
5
|
+
class Resource
|
6
|
+
# Validate the structure of a resource create/update payload.
|
7
|
+
#
|
8
|
+
# @param [Hash] document The input JSONAPI document.
|
9
|
+
# @raise [JSONAPI::Parser::InvalidDocument] if document is invalid.
|
10
|
+
def self.parse!(document)
|
11
|
+
Document.ensure!(document.is_a?(Hash),
|
12
|
+
'A JSON object MUST be at the root of every JSONAPI ' \
|
13
|
+
'request and response containing data.')
|
14
|
+
Document.ensure!(document.keys == ['data'].freeze &&
|
15
|
+
document['data'].is_a?(Hash),
|
16
|
+
'The request MUST include a single resource object ' \
|
17
|
+
'as primary data.')
|
18
|
+
Document.parse_primary_resource!(document['data'])
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
metadata
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: jsonapi-parser
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1.beta3
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Lucas Hosseini
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-10-24 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Parse JSONAPI response documents, resource creation/update payloads,
|
14
|
+
and relationship update payloads.
|
15
|
+
email: lucas.hosseini@gmail.com
|
16
|
+
executables: []
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- README.md
|
21
|
+
- lib/draft.rb
|
22
|
+
- lib/jsonapi/exceptions.rb
|
23
|
+
- lib/jsonapi/parser.rb
|
24
|
+
- lib/jsonapi/parser/document.rb
|
25
|
+
- lib/jsonapi/parser/exceptions.rb
|
26
|
+
- lib/jsonapi/parser/relationship.rb
|
27
|
+
- lib/jsonapi/parser/resource.rb
|
28
|
+
homepage: https://github.com/beauby/jsonapi
|
29
|
+
licenses:
|
30
|
+
- MIT
|
31
|
+
metadata: {}
|
32
|
+
post_install_message:
|
33
|
+
rdoc_options: []
|
34
|
+
require_paths:
|
35
|
+
- lib
|
36
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
42
|
+
requirements:
|
43
|
+
- - ">"
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 1.3.1
|
46
|
+
requirements: []
|
47
|
+
rubyforge_project:
|
48
|
+
rubygems_version: 2.5.1
|
49
|
+
signing_key:
|
50
|
+
specification_version: 4
|
51
|
+
summary: Parse JSONAPI documents.
|
52
|
+
test_files: []
|