1 from decimal
import Decimal
2 from django
.core
.serializers
import deserialize
, serialize
3 from django
.core
.serializers
.base
import DeserializationError
4 from django
.db
import models
5 from django
.test
import TestCase
9 from django
.utils
import simplejson
as json
11 from .fields
import JSONField
, JSONCharField
12 from django
.forms
.util
import ValidationError
14 from collections
import OrderedDict
16 class JsonModel(models
.Model
):
18 default_json
= JSONField(default
={"check":12})
19 complex_default_json
= JSONField(default
=[{"checkcheck": 1212}])
20 empty_default
= JSONField(default
={})
22 class JsonCharModel(models
.Model
):
23 json
= JSONCharField(max_length
=100)
24 default_json
= JSONCharField(max_length
=100, default
={"check":34})
26 class ComplexEncoder(json
.JSONEncoder
):
27 def default(self
, obj
):
28 if isinstance(obj
, complex):
35 return json
.JSONEncoder
.default(self
, obj
)
38 if '__complex__' in dct
:
39 return complex(dct
['real'], dct
['imag'])
42 class JSONModelCustomEncoders(models
.Model
):
43 # A JSON field that can store complex numbers
45 dump_kwargs
={'cls': ComplexEncoder
, "indent": 4},
46 load_kwargs
={'object_hook': as_complex
},
49 class JSONFieldTest(TestCase
):
50 """JSONField Wrapper Tests"""
52 json_model
= JsonModel
54 def test_json_field_create(self
):
55 """Test saving a JSON object in our JSONField"""
57 "item_1": "this is a json blah",
58 "blergh": "hey, hey, hey"}
60 obj
= self
.json_model
.objects
.create(json
=json_obj
)
61 new_obj
= self
.json_model
.objects
.get(id=obj
.id)
63 self
.assertEqual(new_obj
.json
, json_obj
)
65 def test_string_in_json_field(self
):
66 """Test saving an ordinary Python string in our JSONField"""
67 json_obj
= 'blah blah'
68 obj
= self
.json_model
.objects
.create(json
=json_obj
)
69 new_obj
= self
.json_model
.objects
.get(id=obj
.id)
71 self
.assertEqual(new_obj
.json
, json_obj
)
73 def test_float_in_json_field(self
):
74 """Test saving a Python float in our JSONField"""
76 obj
= self
.json_model
.objects
.create(json
=json_obj
)
77 new_obj
= self
.json_model
.objects
.get(id=obj
.id)
79 self
.assertEqual(new_obj
.json
, json_obj
)
81 def test_int_in_json_field(self
):
82 """Test saving a Python integer in our JSONField"""
84 obj
= self
.json_model
.objects
.create(json
=json_obj
)
85 new_obj
= self
.json_model
.objects
.get(id=obj
.id)
87 self
.assertEqual(new_obj
.json
, json_obj
)
89 def test_decimal_in_json_field(self
):
90 """Test saving a Python Decimal in our JSONField"""
91 json_obj
= Decimal(12.34)
92 obj
= self
.json_model
.objects
.create(json
=json_obj
)
93 new_obj
= self
.json_model
.objects
.get(id=obj
.id)
95 # here we must know to convert the returned string back to Decimal,
96 # since json does not support that format
97 self
.assertEqual(Decimal(new_obj
.json
), json_obj
)
99 def test_json_field_modify(self
):
100 """Test modifying a JSON object in our JSONField"""
101 json_obj_1
= {'a': 1, 'b': 2}
102 json_obj_2
= {'a': 3, 'b': 4}
104 obj
= self
.json_model
.objects
.create(json
=json_obj_1
)
105 self
.assertEqual(obj
.json
, json_obj_1
)
106 obj
.json
= json_obj_2
108 self
.assertEqual(obj
.json
, json_obj_2
)
110 self
.assertEqual(obj
.json
, json_obj_2
)
114 def test_json_field_load(self
):
115 """Test loading a JSON object from the DB"""
116 json_obj_1
= {'a': 1, 'b': 2}
117 obj
= self
.json_model
.objects
.create(json
=json_obj_1
)
118 new_obj
= self
.json_model
.objects
.get(id=obj
.id)
120 self
.assertEqual(new_obj
.json
, json_obj_1
)
122 def test_json_list(self
):
123 """Test storing a JSON list"""
124 json_obj
= ["my", "list", "of", 1, "objs", {"hello": "there"}]
126 obj
= self
.json_model
.objects
.create(json
=json_obj
)
127 new_obj
= self
.json_model
.objects
.get(id=obj
.id)
128 self
.assertEqual(new_obj
.json
, json_obj
)
130 def test_empty_objects(self
):
131 """Test storing empty objects"""
132 for json_obj
in [{}, [], 0, '', False]:
133 obj
= self
.json_model
.objects
.create(json
=json_obj
)
134 new_obj
= self
.json_model
.objects
.get(id=obj
.id)
135 self
.assertEqual(json_obj
, obj
.json
)
136 self
.assertEqual(json_obj
, new_obj
.json
)
138 def test_custom_encoder(self
):
139 """Test encoder_cls and object_hook"""
140 value
= 1 + 3j
# A complex number
142 obj
= JSONModelCustomEncoders
.objects
.create(json
=value
)
143 new_obj
= JSONModelCustomEncoders
.objects
.get(pk
=obj
.pk
)
144 self
.assertEqual(value
, new_obj
.json
)
146 def test_django_serializers(self
):
147 """Test serializing/deserializing jsonfield data"""
148 for json_obj
in [{}, [], 0, '', False, {'key': 'value', 'num': 42,
149 'ary': list(range(5)),
150 'dict': {'k': 'v'}}]:
151 obj
= self
.json_model
.objects
.create(json
=json_obj
)
152 new_obj
= self
.json_model
.objects
.get(id=obj
.id)
153 self
.assert_(new_obj
)
155 queryset
= self
.json_model
.objects
.all()
156 ser
= serialize('json', queryset
)
157 for dobj
in deserialize('json', ser
):
159 pulled
= self
.json_model
.objects
.get(id=obj
.pk
)
160 self
.assertEqual(obj
.json
, pulled
.json
)
162 def test_default_parameters(self
):
163 """Test providing a default value to the model"""
165 model
.json
= {"check": 12}
166 self
.assertEqual(model
.json
, {"check": 12})
167 self
.assertEqual(type(model
.json
), dict)
169 self
.assertEqual(model
.default_json
, {"check": 12})
170 self
.assertEqual(type(model
.default_json
), dict)
172 def test_invalid_json(self
):
173 # invalid json data {] in the json and default_json fields
174 ser
= '[{"pk": 1, "model": "jsonfield.jsoncharmodel", ' \
175 '"fields": {"json": "{]", "default_json": "{]"}}]'
176 with self
.assertRaises(DeserializationError
) as cm
:
177 next(deserialize('json', ser
))
178 inner
= cm
.exception
.args
[0]
179 self
.assertTrue(isinstance(inner
, ValidationError
))
180 self
.assertEqual('Enter valid JSON', inner
.messages
[0])
182 def test_integer_in_string_in_json_field(self
):
183 """Test saving the Python string '123' in our JSONField"""
185 obj
= self
.json_model
.objects
.create(json
=json_obj
)
186 new_obj
= self
.json_model
.objects
.get(id=obj
.id)
188 self
.assertEqual(new_obj
.json
, json_obj
)
190 def test_boolean_in_string_in_json_field(self
):
191 """Test saving the Python string 'true' in our JSONField"""
193 obj
= self
.json_model
.objects
.create(json
=json_obj
)
194 new_obj
= self
.json_model
.objects
.get(id=obj
.id)
196 self
.assertEqual(new_obj
.json
, json_obj
)
199 def test_pass_by_reference_pollution(self
):
200 """Make sure the default parameter is copied rather than passed by reference"""
202 model
.default_json
["check"] = 144
203 model
.complex_default_json
[0]["checkcheck"] = 144
204 self
.assertEqual(model
.default_json
["check"], 144)
205 self
.assertEqual(model
.complex_default_json
[0]["checkcheck"], 144)
207 # Make sure when we create a new model, it resets to the default value
208 # and not to what we just set it to (it would be if it were passed by reference)
210 self
.assertEqual(model
.default_json
["check"], 12)
211 self
.assertEqual(model
.complex_default_json
[0]["checkcheck"], 1212)
213 def test_normal_regex_filter(self
):
214 """Make sure JSON model can filter regex"""
216 JsonModel
.objects
.create(json
={"boom": "town"})
217 JsonModel
.objects
.create(json
={"move": "town"})
218 JsonModel
.objects
.create(json
={"save": "town"})
220 self
.assertEqual(JsonModel
.objects
.count(), 3)
222 self
.assertEqual(JsonModel
.objects
.filter(json__regex
=r
"boom").count(), 1)
223 self
.assertEqual(JsonModel
.objects
.filter(json__regex
=r
"town").count(), 3)
225 def test_save_blank_object(self
):
226 """Test that JSON model can save a blank object as none"""
229 self
.assertEqual(model
.empty_default
, {})
232 self
.assertEqual(model
.empty_default
, {})
234 model1
= JsonModel(empty_default
={"hey": "now"})
235 self
.assertEqual(model1
.empty_default
, {"hey": "now"})
238 self
.assertEqual(model1
.empty_default
, {"hey": "now"})
242 class JSONCharFieldTest(JSONFieldTest
):
243 json_model
= JsonCharModel
246 class OrderedJsonModel(models
.Model
):
247 json
= JSONField(load_kwargs
={'object_pairs_hook': OrderedDict
})
250 class OrderedDictSerializationTest(TestCase
):
251 ordered_dict
= OrderedDict([
252 ('number', [1, 2, 3, 4]),
255 expected_key_order
= ['number', 'notes']
257 def test_ordered_dict_differs_from_normal_dict(self
):
258 self
.assertEqual(list(self
.ordered_dict
.keys()), self
.expected_key_order
)
259 self
.assertNotEqual(dict(self
.ordered_dict
).keys(), self
.expected_key_order
)
261 def test_default_behaviour_loses_sort_order(self
):
262 mod
= JsonModel
.objects
.create(json
=self
.ordered_dict
)
263 self
.assertEqual(list(mod
.json
.keys()), self
.expected_key_order
)
264 mod_from_db
= JsonModel
.objects
.get(id=mod
.id)
266 # mod_from_db lost ordering information during json.loads()
267 self
.assertNotEqual(mod_from_db
.json
.keys(), self
.expected_key_order
)
269 def test_load_kwargs_hook_does_not_lose_sort_order(self
):
270 mod
= OrderedJsonModel
.objects
.create(json
=self
.ordered_dict
)
271 self
.assertEqual(list(mod
.json
.keys()), self
.expected_key_order
)
272 mod_from_db
= OrderedJsonModel
.objects
.get(id=mod
.id)
273 self
.assertEqual(list(mod_from_db
.json
.keys()), self
.expected_key_order
)