Skip to content

Gracefully handle no data #290

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Nov 23, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion example/tests/test_parsers.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import json
from io import BytesIO

from django.test import TestCase
from io import BytesIO
from rest_framework.exceptions import ParseError

from rest_framework_json_api.parsers import JSONParser


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

self.assertEqual(data['_meta'], {'random_key': 'random_value'})


def test_parse_include_metadata(self):
parser = JSONParser()

string = json.dumps([])
stream = BytesIO(string.encode('utf-8'))

with self.assertRaises(ParseError):
parser.parse(stream, None, self.parser_context)
76 changes: 38 additions & 38 deletions rest_framework_json_api/parsers.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,44 +59,44 @@ def parse(self, stream, media_type=None, parser_context=None):
Parses the incoming bytestream as JSON and returns the resulting data
"""
result = super(JSONParser, self).parse(stream, media_type=media_type, parser_context=parser_context)
data = result.get('data')

if data:
from rest_framework_json_api.views import RelationshipView
if isinstance(parser_context['view'], RelationshipView):
# We skip parsing the object as JSONAPI Resource Identifier Object and not a regular Resource Object
if isinstance(data, list):
for resource_identifier_object in data:
if not (resource_identifier_object.get('id') and resource_identifier_object.get('type')):
raise ParseError(
'Received data contains one or more malformed JSONAPI Resource Identifier Object(s)'
)
elif not (data.get('id') and data.get('type')):
raise ParseError('Received data is not a valid JSONAPI Resource Identifier Object')

return data

request = parser_context.get('request')

# Check for inconsistencies
resource_name = utils.get_resource_name(parser_context)
if data.get('type') != resource_name and request.method in ('PUT', 'POST', 'PATCH'):
raise exceptions.Conflict(
"The resource object's type ({data_type}) is not the type "
"that constitute the collection represented by the endpoint ({resource_type}).".format(
data_type=data.get('type'),
resource_type=resource_name
)
)
if not data.get('id') and request.method in ('PATCH', 'PUT'):
raise ParseError("The resource identifier object must contain an 'id' member")
if not isinstance(result, dict) or 'data' not in result:
raise ParseError('Received document does not contain primary data')

# Construct the return data
parsed_data = {'id': data.get('id')} if 'id' in data else {}
parsed_data.update(self.parse_attributes(data))
parsed_data.update(self.parse_relationships(data))
parsed_data.update(self.parse_metadata(result))
return parsed_data
data = result.get('data')

else:
raise ParseError('Received document does not contain primary data')
from rest_framework_json_api.views import RelationshipView
if isinstance(parser_context['view'], RelationshipView):
# We skip parsing the object as JSONAPI Resource Identifier Object and not a regular Resource Object
if isinstance(data, list):
for resource_identifier_object in data:
if not (resource_identifier_object.get('id') and resource_identifier_object.get('type')):
raise ParseError(
'Received data contains one or more malformed JSONAPI Resource Identifier Object(s)'
)
elif not (data.get('id') and data.get('type')):
raise ParseError('Received data is not a valid JSONAPI Resource Identifier Object')

return data

request = parser_context.get('request')

# Check for inconsistencies
resource_name = utils.get_resource_name(parser_context)
if data.get('type') != resource_name and request.method in ('PUT', 'POST', 'PATCH'):
raise exceptions.Conflict(
"The resource object's type ({data_type}) is not the type "
"that constitute the collection represented by the endpoint ({resource_type}).".format(
data_type=data.get('type'),
resource_type=resource_name
)
)
if not data.get('id') and request.method in ('PATCH', 'PUT'):
raise ParseError("The resource identifier object must contain an 'id' member")

# Construct the return data
parsed_data = {'id': data.get('id')} if 'id' in data else {}
parsed_data.update(self.parse_attributes(data))
parsed_data.update(self.parse_relationships(data))
parsed_data.update(self.parse_metadata(result))
return parsed_data