Skip to content

Commit 0dca15f

Browse files
author
Tim Heap
committed
Raise a ValidationError on bad JSON in Field.to_python
1 parent c51e654 commit 0dca15f

File tree

2 files changed

+43
-1
lines changed

2 files changed

+43
-1
lines changed

postgres_composite_types/__init__.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import sys
4141
from collections import OrderedDict
4242

43+
from django.core.exceptions import ValidationError
4344
from django.db import migrations, models
4445
from django.db.backends.postgresql.base import \
4546
DatabaseWrapper as PostgresDatabaseWrapper
@@ -112,6 +113,10 @@ class BaseField(models.Field):
112113

113114
Meta = None
114115

116+
default_error_messages = {
117+
'bad_json': "to_python() received a string that was not valid JSON",
118+
}
119+
115120
def db_type(self, connection):
116121
LOGGER.debug("db_type")
117122

@@ -144,7 +149,13 @@ def to_python(self, value):
144149
# is called with a string, assume it was produced by value_to_string
145150
# and decode it
146151
if isinstance(value, str):
147-
value = json.loads(value)
152+
try:
153+
value = json.loads(value)
154+
except ValueError:
155+
raise ValidationError(
156+
self.error_messages['bad_json'],
157+
code='bad_json',
158+
)
148159
return self.Meta.model(**{
149160
name: field.to_python(value.get(name))
150161
for name, field in self.Meta.fields

tests/test_field.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
"""Tests for composite field."""
22

33
import datetime
4+
import json
45
from unittest import mock
56

67
from django.core import serializers
8+
from django.core.exceptions import ValidationError
79
from django.db import connection
810
from django.db.migrations.executor import MigrationExecutor
911
from django.test import TestCase, TransactionTestCase
@@ -164,6 +166,35 @@ def test_serialize(self):
164166
self.assertEqual(old.bounding_box,
165167
new.bounding_box)
166168

169+
def test_to_python(self):
170+
"""
171+
Test the Field.to_python() method interprets strings as JSON data.
172+
"""
173+
start = datetime.datetime.now()
174+
end = datetime.datetime.now() + datetime.timedelta(days=1)
175+
176+
field = NamedDateRange._meta.get_field('date_range')
177+
out = field.to_python(json.dumps({
178+
"start": start.isoformat(),
179+
"end": end.isoformat(),
180+
}))
181+
182+
self.assertEqual(out, DateRange(start=start, end=end))
183+
184+
def test_to_python_bad_json(self):
185+
"""
186+
Test the Field.to_python() handles bad JSON data by raising
187+
a ValidationError
188+
"""
189+
field = NamedDateRange._meta.get_field('date_range')
190+
191+
with self.assertRaises(ValidationError) as context:
192+
field.to_python("bogus JSON")
193+
194+
exception = context.exception
195+
self.assertEqual(exception.code, 'bad_json')
196+
197+
167198

168199
class TestOptionalFields(TestCase):
169200
"""

0 commit comments

Comments
 (0)