Skip to content

Commit a85470f

Browse files
committed
begin playing with using JSON API for deserialization
1 parent a032201 commit a85470f

File tree

2 files changed

+24
-61
lines changed

2 files changed

+24
-61
lines changed

lib/active_model_serializers/adapter/json_api/deserialization.rb

Lines changed: 12 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1+
require 'jsonapi'
2+
13
module ActiveModelSerializers
24
module Adapter
35
class JsonApi
46
# NOTE(Experimental):
57
# This is an experimental feature. Both the interface and internals could be subject
68
# to changes.
79
module Deserialization
8-
InvalidDocument = Class.new(ArgumentError)
9-
1010
module_function
1111

1212
# Transform a JSON API document, containing a single data object,
@@ -74,21 +74,21 @@ module Deserialization
7474
#
7575
def parse!(document, options = {})
7676
parse(document, options) do |invalid_payload, reason|
77-
fail InvalidDocument, "Invalid payload (#{reason}): #{invalid_payload}"
77+
fail JSONAPI::InvalidDocument, "Invalid payload (#{reason}): #{invalid_payload}"
7878
end
7979
end
8080

8181
# Same as parse!, but returns an empty hash instead of raising InvalidDocument
8282
# on invalid payloads.
8383
def parse(document, options = {})
84-
document = document.dup.permit!.to_h if document.is_a?(ActionController::Parameters)
85-
86-
validate_payload(document) do |invalid_document, reason|
87-
yield invalid_document, reason if block_given?
88-
return {}
89-
end
84+
document = JSONAPI.parse(document, options)
85+
document = document.to_hash
9086

9187
primary_data = document['data']
88+
89+
# null data is allowed, as per the JSON API Schema
90+
return {} unless primary_data
91+
9292
attributes = primary_data['attributes'] || {}
9393
attributes['id'] = primary_data['id'] if primary_data['id']
9494
relationships = primary_data['relationships'] || {}
@@ -101,43 +101,11 @@ def parse(document, options = {})
101101
hash.merge!(parse_relationships(relationships, options))
102102

103103
hash
104-
end
105-
106-
# Checks whether a payload is compliant with the JSON API spec.
107-
#
108-
# @api private
109-
# rubocop:disable Metrics/CyclomaticComplexity
110-
def validate_payload(payload)
111-
unless payload.is_a?(Hash)
112-
yield payload, 'Expected hash'
113-
return
114-
end
115104

116-
primary_data = payload['data']
117-
unless primary_data.is_a?(Hash)
118-
yield payload, { data: 'Expected hash' }
119-
return
120-
end
121-
122-
attributes = primary_data['attributes'] || {}
123-
unless attributes.is_a?(Hash)
124-
yield payload, { data: { attributes: 'Expected hash or nil' } }
125-
return
126-
end
127-
128-
relationships = primary_data['relationships'] || {}
129-
unless relationships.is_a?(Hash)
130-
yield payload, { data: { relationships: 'Expected hash or nil' } }
131-
return
132-
end
133-
134-
relationships.each do |(key, value)|
135-
unless value.is_a?(Hash) && value.key?('data')
136-
yield payload, { data: { relationships: { key => 'Expected hash with :data key' } } }
137-
end
138-
end
105+
rescue JSONAPI::InvalidDocument
106+
return {} unless block_given?
107+
yield
139108
end
140-
# rubocop:enable Metrics/CyclomaticComplexity
141109

142110
# @api private
143111
def filter_fields(fields, options)

test/adapter/json_api/parse_test.rb

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ module ActiveModelSerializers
33
module Adapter
44
class JsonApi
55
module Deserialization
6-
class ParseTest < Minitest::Test
6+
class ParseTest < ActiveSupport::TestCase
77
def setup
88
@hash = {
99
'data' => {
@@ -41,21 +41,11 @@ def setup
4141

4242
@illformed_payloads = [nil,
4343
{},
44-
{
45-
'data' => nil
46-
}, {
47-
'data' => { 'attributes' => [] }
48-
}, {
49-
'data' => { 'relationships' => [] }
50-
}, {
51-
'data' => {
52-
'relationships' => { 'rel' => nil }
53-
}
54-
}, {
55-
'data' => {
56-
'relationships' => { 'rel' => {} }
57-
}
58-
}]
44+
{ 'data' => { 'attributes' => [] } },
45+
{ 'data' => { 'relationships' => [] } },
46+
{ 'data' => { 'relationships' => { 'rel' => nil } } },
47+
{ 'data' => { 'relationships' => { 'rel' => {} } } }
48+
]
5949
end
6050

6151
def test_hash
@@ -76,9 +66,14 @@ def test_illformed_payloads_safe
7666
end
7767
end
7868

69+
test 'null data is allow per the JSON API Schema' do
70+
parsed_hash = ActiveModelSerializers::Adapter::JsonApi::Deserialization.parse!('data' => nil)
71+
assert_equal({}, parsed_hash)
72+
end
73+
7974
def test_illformed_payloads_unsafe
8075
@illformed_payloads.each do |p|
81-
assert_raises(InvalidDocument) do
76+
assert_raises(JSONAPI::InvalidDocument) do
8277
ActiveModelSerializers::Adapter::JsonApi::Deserialization.parse!(p)
8378
end
8479
end

0 commit comments

Comments
 (0)