Skip to content
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
9 changes: 9 additions & 0 deletions django_custom_jsonfield/rest_framework/serializers.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,25 @@
import jsonschema
from django.utils.translation import gettext_lazy as _
from jsonschema import validators
from rest_framework import serializers


class CustomJSONField(serializers.JSONField):
default_error_messages = {
"invalid_data": _("Value does not match the JSON schema."),
"invalid_schema": _("Invalid JSON schema."),
}

def __init__(self, schema: dict, **kwargs):
self.schema = schema
super().__init__(**kwargs)

validator = validators.validator_for(self.schema)
try:
validator.check_schema(self.schema)
except jsonschema.exceptions.SchemaError:
self.fail("invalid_schema")

self.validators.append(self._validate_data)

def _validate_data(self, value):
Expand Down
14 changes: 9 additions & 5 deletions tests/test_openapi_schema.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from typing import Any
from unittest.mock import Mock
from unittest.mock import Mock, patch

import pytest

Expand Down Expand Up @@ -76,12 +76,16 @@ def test_map_serializer_field_const(schema: dict, expected: Any):
@pytest.mark.parametrize(
"schema",
[
{
"type": "test",
},
{"type": "unknown_type"},
],
)
def test_map_serializer_field_invalid_schema(schema: dict):
@patch(
"django_custom_jsonfield.rest_framework.serializers.jsonschema.validators.validator_for",
new=Mock(),
)
def test_map_serializer_field_fallback(schema: Any):
"""Test fallback to string."""

json_field = CustomJSONField(schema=schema)
extension = CustomJSONFieldSerializerExtension(json_field)
data = extension.map_serializer_field(Mock(), "response")
Expand Down
24 changes: 21 additions & 3 deletions tests/test_serializer_field.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import pytest
from rest_framework import serializers
from rest_framework.exceptions import ErrorDetail
from rest_framework import exceptions, serializers

from django_custom_jsonfield.rest_framework.serializers import CustomJSONField

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

expected_errors = {
"json_field": [
ErrorDetail(
exceptions.ErrorDetail(
string="Value does not match the JSON schema.",
code="invalid_data",
),
],
}
assert serializer.errors == expected_errors


@pytest.mark.parametrize(
"schema",
[
{"minItems": "1"},
{"properties": 1},
{"pattern": "*invalid.regex"},
],
)
def test_map_serializer_field_invalid_schema(schema: dict):
"""Test serializer raises an exception if JSON schema is invalid."""

with pytest.raises(exceptions.ValidationError) as e:
CustomJSONField(schema=schema)

assert isinstance(e.value, exceptions.ValidationError)
assert e.value.detail[0] == "Invalid JSON schema."
assert e.value.detail[0].code == "invalid_schema"