More sensible full serialization

This commit is contained in:
Jakub Warmuz 2015-03-27 19:55:26 +00:00
parent 3762622ee9
commit 1349b5241c
No known key found for this signature in database
GPG key ID: 2A7BAD3A489B52EA
2 changed files with 27 additions and 12 deletions

View file

@ -129,18 +129,24 @@ class JSONDeSerializable(object):
:returns: Fully serialized object.
"""
partial = self.to_json()
try_serialize = (lambda x: x.fully_serialize()
if isinstance(x, JSONDeSerializable) else x)
if isinstance(partial, basestring): # strings are sequences
return partial
if isinstance(partial, collections.Sequence):
return [try_serialize(elem) for elem in partial]
elif isinstance(partial, collections.Mapping):
return dict([(try_serialize(key), try_serialize(value))
for key, value in partial.iteritems()])
else:
return partial
def _serialize(obj):
if isinstance(obj, JSONDeSerializable):
return _serialize(obj.to_json())
if isinstance(obj, basestring): # strings are sequence
return obj
elif isinstance(obj, list):
return [_serialize(subobj) for subobj in obj]
elif isinstance(obj, collections.Sequence):
# default to tuple, otherwise Mapping could get
# unhashable list
return tuple(_serialize(subobj) for subobj in obj)
elif isinstance(obj, collections.Mapping):
return dict((_serialize(key), _serialize(value))
for key, value in obj.iteritems())
else:
return obj
return _serialize(self)
@util.abstractclassmethod
def from_json(cls, unused_jobj):

View file

@ -3,6 +3,7 @@ import unittest
class JSONDeSerializableTest(unittest.TestCase):
# pylint: disable=too-many-instance-attributes
def setUp(self):
from letsencrypt.acme.jose.interfaces import JSONDeSerializable
@ -50,6 +51,8 @@ class JSONDeSerializableTest(unittest.TestCase):
self.basic2 = Basic('foo2')
self.seq = Sequence(self.basic1, self.basic2)
self.mapping = Mapping(self.basic1, self.basic2)
self.nested = Basic([[self.basic1]])
self.tuple = Basic(('foo',))
# pylint: disable=invalid-name
self.Basic = Basic
@ -66,6 +69,12 @@ class JSONDeSerializableTest(unittest.TestCase):
mock_value = object()
self.assertTrue(self.Basic(mock_value).fully_serialize() is mock_value)
def test_fully_serialize_nested(self):
self.assertEqual(self.nested.fully_serialize(), [['foo1']])
def test_fully_serialize(self):
self.assertEqual(self.tuple.fully_serialize(), (('foo', )))
def test_from_json_not_implemented(self):
from letsencrypt.acme.jose.interfaces import JSONDeSerializable
self.assertRaises(TypeError, JSONDeSerializable.from_json, 'xxx')