Skip to content

Commit 07f464e

Browse files
jmphillidanielhochman
authored andcommitted
Serialize UnicodeSetAttributes correctly (#151)
1 parent 96db7db commit 07f464e

File tree

2 files changed

+59
-3
lines changed

2 files changed

+59
-3
lines changed

pynamodb/attributes.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,48 @@ class UnicodeSetAttribute(SetMixin, Attribute):
144144
attr_type = STRING_SET
145145
null = True
146146

147+
def element_serialize(self, value):
148+
"""
149+
This serializes unicode / strings out as unicode strings.
150+
It does not touch the value if it is already a unicode str
151+
:param value:
152+
:return:
153+
"""
154+
if isinstance(value, six.text_type):
155+
return value
156+
return six.u(str(value))
157+
158+
def element_deserialize(self, value):
159+
"""
160+
This deserializes what we get from mongo back into a str
161+
Serialization previously json encoded strings. This caused them to have
162+
extra double quote (") characters. That no longer happens.
163+
This method allows both types of serialized values to be read
164+
:param value:
165+
:return:
166+
"""
167+
result = value
168+
try:
169+
result = json.loads(value)
170+
except ValueError:
171+
# it's serialized in the new way so pass
172+
pass
173+
return result
174+
175+
def serialize(self, value):
176+
if value is not None:
177+
try:
178+
iter(value)
179+
except TypeError:
180+
value = [value]
181+
if len(value):
182+
return [self.element_serialize(val) for val in sorted(value)]
183+
return None
184+
185+
def deserialize(self, value):
186+
if value and len(value):
187+
return set([self.element_deserialize(val) for val in value])
188+
147189

148190
class UnicodeAttribute(Attribute):
149191
"""

pynamodb/tests/test_attributes.py

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,8 @@ def test_unicode_set_serialize(self):
335335
self.assertEqual(attr.deserialize(None), None)
336336
self.assertEqual(
337337
attr.serialize(set([six.u('foo'), six.u('bar')])),
338-
[json.dumps(val) for val in sorted(set([six.u('foo'), six.u('bar')]))])
338+
sorted([six.u('foo'), six.u('bar')])
339+
)
339340

340341
def test_round_trip_unicode_set(self):
341342
"""
@@ -353,9 +354,22 @@ def test_unicode_set_deserialize(self):
353354
UnicodeSetAttribute.deserialize
354355
"""
355356
attr = UnicodeSetAttribute()
357+
value = set([six.u('foo'), six.u('bar')])
358+
self.assertEqual(
359+
attr.deserialize(value),
360+
value
361+
)
362+
363+
def test_unicode_set_deserialize(self):
364+
"""
365+
UnicodeSetAttribute.deserialize old way
366+
"""
367+
attr = UnicodeSetAttribute()
368+
value = set([six.u('foo'), six.u('bar')])
369+
old_value = set([json.dumps(val) for val in value])
356370
self.assertEqual(
357-
attr.deserialize([json.dumps(val) for val in sorted(set([six.u('foo'), six.u('bar')]))]),
358-
set([six.u('foo'), six.u('bar')])
371+
attr.deserialize(old_value),
372+
value
359373
)
360374

361375
def test_unicode_set_attribute(self):

0 commit comments

Comments
 (0)