Skip to content

Commit 7bf364d

Browse files
committed
Add schema validation in CustomJSONField serializer
Add schema validation in CustomJSONField serializer
1 parent f124e60 commit 7bf364d

File tree

3 files changed

+40
-8
lines changed

3 files changed

+40
-8
lines changed

django_custom_jsonfield/rest_framework/serializers.py

+9
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,25 @@
11
import jsonschema
22
from django.utils.translation import gettext_lazy as _
3+
from jsonschema import validators
34
from rest_framework import serializers
45

56

67
class CustomJSONField(serializers.JSONField):
78
default_error_messages = {
89
"invalid_data": _("Value does not match the JSON schema."),
10+
"invalid_schema": _("Invalid JSON schema."),
911
}
1012

1113
def __init__(self, schema: dict, **kwargs):
1214
self.schema = schema
1315
super().__init__(**kwargs)
16+
17+
validator = validators.validator_for(self.schema)
18+
try:
19+
validator.check_schema(self.schema)
20+
except jsonschema.exceptions.SchemaError:
21+
self.fail("invalid_schema")
22+
1423
self.validators.append(self._validate_data)
1524

1625
def _validate_data(self, value):

tests/test_openapi_schema.py

+10-5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
from unittest.mock import Mock
1+
from typing import Any
2+
from unittest.mock import Mock, patch
23

34
import pytest
45

@@ -53,12 +54,16 @@ def test_map_serializer_field_ok(schema: dict):
5354
@pytest.mark.parametrize(
5455
"schema",
5556
[
56-
{
57-
"type": "test",
58-
},
57+
{"type": "unknown_type"},
5958
],
6059
)
61-
def test_map_serializer_field_invalid_schema(schema: dict):
60+
@patch(
61+
"django_custom_jsonfield.rest_framework.serializers.jsonschema.validators.validator_for",
62+
new=Mock(),
63+
)
64+
def test_map_serializer_field_fallback(schema: Any):
65+
"""Test fallback to string."""
66+
6267
json_field = CustomJSONField(schema=schema)
6368
extension = CustomJSONFieldSerializerExtension(json_field)
6469
data = extension.map_serializer_field(Mock(), "response")

tests/test_serializer_field.py

+21-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import pytest
2-
from rest_framework import serializers
3-
from rest_framework.exceptions import ErrorDetail
2+
from rest_framework import exceptions, serializers
43

54
from django_custom_jsonfield.rest_framework.serializers import CustomJSONField
65

@@ -27,10 +26,29 @@ class FakeSerializer(serializers.Serializer):
2726

2827
expected_errors = {
2928
"json_field": [
30-
ErrorDetail(
29+
exceptions.ErrorDetail(
3130
string="Value does not match the JSON schema.",
3231
code="invalid_data",
3332
),
3433
],
3534
}
3635
assert serializer.errors == expected_errors
36+
37+
38+
@pytest.mark.parametrize(
39+
"schema",
40+
[
41+
{"minItems": "1"},
42+
{"properties": 1},
43+
{"pattern": "*invalid.regex"},
44+
],
45+
)
46+
def test_map_serializer_field_invalid_schema(schema: dict):
47+
"""Test serializer raises an exception if JSON schema is invalid."""
48+
49+
with pytest.raises(exceptions.ValidationError) as e:
50+
CustomJSONField(schema=schema)
51+
52+
assert isinstance(e.value, exceptions.ValidationError)
53+
assert e.value.detail[0] == "Invalid JSON schema."
54+
assert e.value.detail[0].code == "invalid_schema"

0 commit comments

Comments
 (0)