Fixed #30583 -- Fixed handling JSONFields in XML serializer.

Co-authored-by: Chason Chaffin <chason@gmail.com>
This commit is contained in:
Hasan Ramezani 2020-03-23 19:31:49 +01:00 committed by Mariusz Felisiak
parent 82da72b748
commit 47651eadb8
2 changed files with 25 additions and 2 deletions

View File

@ -1,7 +1,7 @@
""" """
XML serializer. XML serializer.
""" """
import json
from xml.dom import pulldom from xml.dom import pulldom
from xml.sax import handler from xml.sax import handler
from xml.sax.expatreader import ExpatParser as _ExpatParser from xml.sax.expatreader import ExpatParser as _ExpatParser
@ -75,8 +75,13 @@ class Serializer(base.Serializer):
# Get a "string version" of the object's data. # Get a "string version" of the object's data.
if getattr(obj, field.name) is not None: if getattr(obj, field.name) is not None:
value = field.value_to_string(obj)
if field.get_internal_type() == 'JSONField':
# Dump value since JSONField.value_to_string() doesn't output
# strings.
value = json.dumps(value, cls=field.encoder)
try: try:
self.xml.characters(field.value_to_string(obj)) self.xml.characters(value)
except UnserializableContentError: except UnserializableContentError:
raise ValueError("%s.%s (pk:%s) contains unserializable characters" % ( raise ValueError("%s.%s (pk:%s) contains unserializable characters" % (
obj.__class__.__name__, field.name, obj.pk)) obj.__class__.__name__, field.name, obj.pk))
@ -232,6 +237,9 @@ class Deserializer(base.Deserializer):
value = None value = None
else: else:
value = field.to_python(getInnerText(field_node).strip()) value = field.to_python(getInnerText(field_node).strip())
# Load value since JSONField.to_python() outputs strings.
if field.get_internal_type() == 'JSONField':
value = json.loads(value, cls=field.decoder)
data[field.name] = value data[field.name] = value
obj = base.build_instance(Model, data, self.db) obj = base.build_instance(Model, data, self.db)

View File

@ -149,6 +149,21 @@ class TestSerialization(SimpleTestCase):
)[0].object )[0].object
self.assertEqual(instance.value, value) self.assertEqual(instance.value, value)
def test_xml_serialization(self):
test_xml_data = (
'<django-objects version="1.0">'
'<object model="model_fields.nullablejsonmodel">'
'<field name="value" type="JSONField">%s'
'</field></object></django-objects>'
)
for value, serialized in self.test_values:
with self.subTest(value=value):
instance = NullableJSONModel(value=value)
data = serializers.serialize('xml', [instance], fields=['value'])
self.assertXMLEqual(data, test_xml_data % serialized)
new_instance = list(serializers.deserialize('xml', data))[0].object
self.assertEqual(new_instance.value, instance.value)
@skipUnlessDBFeature('supports_json_field') @skipUnlessDBFeature('supports_json_field')
class TestSaveLoad(TestCase): class TestSaveLoad(TestCase):