Skip to content

Commit c869f34

Browse files
authored
Merge pull request #290 from amw/gracefully-handle-no-data
Gracefully handle no data
2 parents b656323 + 0cfe2e1 commit c869f34

File tree

2 files changed

+51
-39
lines changed

2 files changed

+51
-39
lines changed

example/tests/test_parsers.py

+13-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import json
2+
from io import BytesIO
23

34
from django.test import TestCase
4-
from io import BytesIO
5+
from rest_framework.exceptions import ParseError
6+
57
from rest_framework_json_api.parsers import JSONParser
68

79

@@ -36,3 +38,13 @@ def test_parse_include_metadata(self):
3638
data = parser.parse(stream, None, self.parser_context)
3739

3840
self.assertEqual(data['_meta'], {'random_key': 'random_value'})
41+
42+
43+
def test_parse_include_metadata(self):
44+
parser = JSONParser()
45+
46+
string = json.dumps([])
47+
stream = BytesIO(string.encode('utf-8'))
48+
49+
with self.assertRaises(ParseError):
50+
parser.parse(stream, None, self.parser_context)

rest_framework_json_api/parsers.py

+38-38
Original file line numberDiff line numberDiff line change
@@ -59,44 +59,44 @@ def parse(self, stream, media_type=None, parser_context=None):
5959
Parses the incoming bytestream as JSON and returns the resulting data
6060
"""
6161
result = super(JSONParser, self).parse(stream, media_type=media_type, parser_context=parser_context)
62-
data = result.get('data')
6362

64-
if data:
65-
from rest_framework_json_api.views import RelationshipView
66-
if isinstance(parser_context['view'], RelationshipView):
67-
# We skip parsing the object as JSONAPI Resource Identifier Object and not a regular Resource Object
68-
if isinstance(data, list):
69-
for resource_identifier_object in data:
70-
if not (resource_identifier_object.get('id') and resource_identifier_object.get('type')):
71-
raise ParseError(
72-
'Received data contains one or more malformed JSONAPI Resource Identifier Object(s)'
73-
)
74-
elif not (data.get('id') and data.get('type')):
75-
raise ParseError('Received data is not a valid JSONAPI Resource Identifier Object')
76-
77-
return data
78-
79-
request = parser_context.get('request')
80-
81-
# Check for inconsistencies
82-
resource_name = utils.get_resource_name(parser_context)
83-
if data.get('type') != resource_name and request.method in ('PUT', 'POST', 'PATCH'):
84-
raise exceptions.Conflict(
85-
"The resource object's type ({data_type}) is not the type "
86-
"that constitute the collection represented by the endpoint ({resource_type}).".format(
87-
data_type=data.get('type'),
88-
resource_type=resource_name
89-
)
90-
)
91-
if not data.get('id') and request.method in ('PATCH', 'PUT'):
92-
raise ParseError("The resource identifier object must contain an 'id' member")
63+
if not isinstance(result, dict) or 'data' not in result:
64+
raise ParseError('Received document does not contain primary data')
9365

94-
# Construct the return data
95-
parsed_data = {'id': data.get('id')} if 'id' in data else {}
96-
parsed_data.update(self.parse_attributes(data))
97-
parsed_data.update(self.parse_relationships(data))
98-
parsed_data.update(self.parse_metadata(result))
99-
return parsed_data
66+
data = result.get('data')
10067

101-
else:
102-
raise ParseError('Received document does not contain primary data')
68+
from rest_framework_json_api.views import RelationshipView
69+
if isinstance(parser_context['view'], RelationshipView):
70+
# We skip parsing the object as JSONAPI Resource Identifier Object and not a regular Resource Object
71+
if isinstance(data, list):
72+
for resource_identifier_object in data:
73+
if not (resource_identifier_object.get('id') and resource_identifier_object.get('type')):
74+
raise ParseError(
75+
'Received data contains one or more malformed JSONAPI Resource Identifier Object(s)'
76+
)
77+
elif not (data.get('id') and data.get('type')):
78+
raise ParseError('Received data is not a valid JSONAPI Resource Identifier Object')
79+
80+
return data
81+
82+
request = parser_context.get('request')
83+
84+
# Check for inconsistencies
85+
resource_name = utils.get_resource_name(parser_context)
86+
if data.get('type') != resource_name and request.method in ('PUT', 'POST', 'PATCH'):
87+
raise exceptions.Conflict(
88+
"The resource object's type ({data_type}) is not the type "
89+
"that constitute the collection represented by the endpoint ({resource_type}).".format(
90+
data_type=data.get('type'),
91+
resource_type=resource_name
92+
)
93+
)
94+
if not data.get('id') and request.method in ('PATCH', 'PUT'):
95+
raise ParseError("The resource identifier object must contain an 'id' member")
96+
97+
# Construct the return data
98+
parsed_data = {'id': data.get('id')} if 'id' in data else {}
99+
parsed_data.update(self.parse_attributes(data))
100+
parsed_data.update(self.parse_relationships(data))
101+
parsed_data.update(self.parse_metadata(result))
102+
return parsed_data

0 commit comments

Comments
 (0)