From b0c7488669d1890b2d3a8394b4ae247130ddb0b1 Mon Sep 17 00:00:00 2001 From: Hamed Ahmadi Date: Thu, 21 Jul 2016 10:01:06 -0700 Subject: [PATCH 1/2] Include metadata in Parser output The JSONParser will add metadata in the request under a top level key '_meta'. --- example/tests/test_parsers.py | 38 ++++++++++++++++++++++++++++++ rest_framework_json_api/parsers.py | 9 +++++++ 2 files changed, 47 insertions(+) create mode 100644 example/tests/test_parsers.py diff --git a/example/tests/test_parsers.py b/example/tests/test_parsers.py new file mode 100644 index 00000000..9da1f09c --- /dev/null +++ b/example/tests/test_parsers.py @@ -0,0 +1,38 @@ +import json + +from django.test import TestCase +from io import BytesIO +from rest_framework_json_api.parsers import JSONParser + + +class TestJSONParser(TestCase): + + def setUp(self): + class MockRequest(object): + + def __init__(self): + self.method = 'GET' + + request = MockRequest() + + self.parser_context = {'request': request, 'kwargs': {}, 'view': 'BlogViewSet'} + + data = { + 'data': { + 'id': 123, + 'type': 'Blog' + }, + 'meta': { + 'random_key': 'random_value' + } + } + + self.string = json.dumps(data) + + def test_parse_include_metadata(self): + parser = JSONParser() + + stream = BytesIO(self.string.encode('utf-8')) + data = parser.parse(stream, None, self.parser_context) + + self.assertEqual(data['_meta'], {'random_key': 'random_value'}) diff --git a/rest_framework_json_api/parsers.py b/rest_framework_json_api/parsers.py index dc24a2df..a0c53f05 100644 --- a/rest_framework_json_api/parsers.py +++ b/rest_framework_json_api/parsers.py @@ -46,6 +46,14 @@ def parse_relationships(data): parsed_relationships[field_name] = list(relation for relation in field_data) return parsed_relationships + @staticmethod + def parse_metadata(result): + metadata = result.get('meta') + if metadata: + return {'_meta': metadata} + else: + return {} + def parse(self, stream, media_type=None, parser_context=None): """ Parses the incoming bytestream as JSON and returns the resulting data @@ -87,6 +95,7 @@ def parse(self, stream, media_type=None, parser_context=None): parsed_data = {'id': data.get('id')} parsed_data.update(self.parse_attributes(data)) parsed_data.update(self.parse_relationships(data)) + parsed_data.update(self.parse_metadata(result)) return parsed_data else: From 2cdb15d55947ca503bed0884759a4a626ecffc83 Mon Sep 17 00:00:00 2001 From: Hamed Ahmadi Date: Tue, 16 Aug 2016 12:21:57 -0700 Subject: [PATCH 2/2] Documenting parsing metadata in request body --- docs/api.md | 11 +++++++++++ docs/usage.md | 4 +++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/docs/api.md b/docs/api.md index a7f8926f..86116d5c 100644 --- a/docs/api.md +++ b/docs/api.md @@ -47,3 +47,14 @@ Calls a `get_root_meta` function on a serializer, if it exists. `build_json_resource_obj(fields, resource, resource_instance, resource_name)` Builds the resource object (type, id, attributes) and extracts relationships. + +## rest_framework_json_api.parsers.JSONParser + +Similar to `JSONRenderer`, the `JSONParser` you may override the following methods if you need +highly custom parsing control. + +#### parse_metadata + +`parse_metadata(result)` + +Returns a dictionary which will be merged into parsed data of the request. By default, it reads the `meta` content in the request body and returns it in a dictionary with a `_meta` top level key. diff --git a/docs/usage.md b/docs/usage.md index 68196174..c1c966b7 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -375,7 +375,7 @@ class LineItemViewSet(viewsets.ModelViewSet): ### RelationshipView `rest_framework_json_api.views.RelationshipView` is used to build -relationship views (see the +relationship views (see the [JSON API spec](http://jsonapi.org/format/#fetching-relationships)). The `self` link on a relationship object should point to the corresponding relationship view. @@ -449,6 +449,8 @@ def get_root_meta(self, resource, many): ``` to the serializer. It must return a dict and will be merged with the existing top level `meta`. +To access metadata in incoming requests, the `JSONParser` will add the metadata under a top level `_meta` key in the parsed data dictionary. For instance, to access meta data from a `serializer` object, you may use `serializer.initial_data.get("_meta")`. To customize the `_meta` key, see [here](api.md). + ### Links Adding `url` to `fields` on a serializer will add a `self` link to the `links` key.