Merge lp:~wallyworld/lazr.json/deserialisation-sometimes-fails-987043 into lp:lazr.json

Proposed by Ian Booth
Status: Merged
Approved by: Ian Booth
Approved revision: 5
Merged at revision: 4
Proposed branch: lp:~wallyworld/lazr.json/deserialisation-sometimes-fails-987043
Merge into: lp:lazr.json
Diff against target: 140 lines (+35/-13)
4 files modified
src/lazr/json/NEWS.txt (+5/-0)
src/lazr/json/README.txt (+18/-7)
src/lazr/json/_serialisation.py (+11/-5)
src/lazr/json/version.txt (+1/-1)
To merge this branch: bzr merge lp:~wallyworld/lazr.json/deserialisation-sometimes-fails-987043
Reviewer Review Type Date Requested Status
Ian Booth (community) Approve
Review via email: mp+103033@code.launchpad.net

Commit message

Ensure single value dicts are properly deserialised.

Description of the change

== Implementation ==

Tweak to deccoder to ensure that single value dicts are decoded properly. Previously, a single value dict would always be interpreted as an encoded object and attempts to deserialise it would result in failure.

== Tests ==

Add extra doc tests to README.txt

== Lint ==

Lint free apart from false positives.

To post a comment you must log in.
Revision history for this message
Ian Booth (wallyworld) wrote :

Minor change, self reviewed.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/lazr/json/NEWS.txt'
2--- src/lazr/json/NEWS.txt 2012-04-19 07:41:21 +0000
3+++ src/lazr/json/NEWS.txt 2012-04-23 00:33:18 +0000
4@@ -2,6 +2,11 @@
5 NEWS for lazr.json
6 =====================
7
8+0.2 (2012-04-23)
9+================
10+
11+- Fix issue with deserialising single value dicts (bug 987043)
12+
13 0.1 (2012-04-19)
14 ================
15
16
17=== modified file 'src/lazr/json/README.txt'
18--- src/lazr/json/README.txt 2012-04-19 23:21:21 +0000
19+++ src/lazr/json/README.txt 2012-04-23 00:33:18 +0000
20@@ -69,7 +69,7 @@
21
22 >>> register_serialisable_type("complex", ComplexObject)
23 >>> print json.dumps(obj, cls=CustomTypeEncoder)
24- {"complex,__builtin__.ComplexObject":
25+ {"%complex,__builtin__.ComplexObject%":
26 {"f_int": 5, "f_string": "string_value"}}
27
28 We can register an encoder for a complex object.
29@@ -88,7 +88,7 @@
30 The json encoding of the object is changed accordingly.
31
32 >>> print json.dumps(obj, cls=CustomTypeEncoder)
33- {"complex,__builtin__.ComplexObject":
34+ {"%complex,__builtin__.ComplexObject%":
35 "{\"int_value\": 5, \"str_value\": \"string_value\"}"}
36
37 Arbitrarily complex objects are supported, including those with complex
38@@ -101,8 +101,8 @@
39 >>> register_serialisable_type("another", AnotherComplexObject)
40 >>> another = AnotherComplexObject()
41 >>> print json.dumps(another, cls=CustomTypeEncoder)
42- {"another,__builtin__.AnotherComplexObject":
43- {"obj": {"complex,__builtin__.ComplexObject":
44+ {"%another,__builtin__.AnotherComplexObject%":
45+ {"obj": {"%complex,__builtin__.ComplexObject%":
46 "{\"int_value\": 5, \"str_value\": \"string_value\"}"}}}
47
48 Collections of complex objects can be serialised.
49@@ -110,7 +110,7 @@
50 >>> complex_collection = [ComplexObject() for x in range(4)]
51 >>> json_collection = json.dumps(complex_collection, cls=CustomTypeEncoder)
52 >>> print json_collection
53- [{"complex,__builtin__.ComplexObject":
54+ [{"%complex,__builtin__.ComplexObject%":
55 "{\"int_value\": 5, \"str_value\": \"string_value\"}"}, ...]
56
57 ==========================
58@@ -131,7 +131,7 @@
59
60 >>> an_apple = Fruit.APPLE
61 >>> print json.dumps(an_apple, cls=CustomTypeEncoder)
62- {"BaseItem,lazr.enum._enum.Item": "{\"type\": \"Fruit\", \"name\": \"APPLE\"}"}
63+ {"%BaseItem,lazr.enum._enum.Item%": "{\"type\": \"Fruit\", \"name\": \"APPLE\"}"}
64
65
66 ======================
67@@ -200,6 +200,18 @@
68 >>> print deserialised == obj
69 True
70
71+Single value dicts which look like (but are not) serialised objects are
72+correctly handled.
73+ >>> dict_val = json.loads('{"a": 123}', object_hook=custom_type_decoder)
74+ >>> print dict_val
75+ {u'a': 123}
76+ >>> dict_val = json.loads('{"a,b": 123}', object_hook=custom_type_decoder)
77+ >>> print dict_val
78+ {u'a,b': 123}
79+ >>> dict_val = json.loads('{"%a,b%": 123}', object_hook=custom_type_decoder)
80+ >>> print dict_val
81+ {u'%a,b%': 123}
82+
83 ============================
84 Deserialising Built In Types
85 ============================
86@@ -225,4 +237,3 @@
87
88 *
89 docs/*
90-
91
92=== modified file 'src/lazr/json/_serialisation.py'
93--- src/lazr/json/_serialisation.py 2012-04-19 23:21:21 +0000
94+++ src/lazr/json/_serialisation.py 2012-04-23 00:33:18 +0000
95@@ -41,7 +41,7 @@
96 """A custom JSONEncoder class that knows how to encode custom objects.
97
98 Custom objects are encoded as JSON object literals with a single key,
99- 'type_name,full_classname' where:
100+ '%type_name,full_classname%' where:
101 type_name is the name key taken from _SERIALISATION_TYPES
102 full_classname is the classname of the object being serialised
103
104@@ -64,7 +64,7 @@
105 if len(class_info) > 1:
106 encoder = class_info[1]
107 if isinstance(obj, obj_type):
108- key = ('%s,%s.%s'
109+ key = ('%%%s,%s.%s%%'
110 % (type_name, obj.__module__, obj.__class__.__name__))
111 if encoder is None:
112 encoded_value = obj.__dict__
113@@ -102,11 +102,17 @@
114 if len(json_dict) == 1:
115 # Determine the type_name and classname.
116 classname_info, json_value = json_dict.items()[0]
117- type_name, specific_obj_classname = classname_info.split(',')
118- # If no registered decoder, return the raw value.
119+ if (classname_info.find(',') < 0
120+ or not classname_info.startswith('%')
121+ or not classname_info.endswith('%')):
122+ return json_dict
123+ type_name, specific_obj_classname = (
124+ classname_info.strip('%').split(','))
125+ # If type is not registered or we don't have a valid object classname,
126+ # return the raw value.
127 class_info = _SERIALISABLE_TYPES.get(type_name)
128 if not class_info:
129- return json_value
130+ return json_dict
131 # Attempt to import the object's specific class.
132 specific_obj_class = _import(specific_obj_classname)
133 if specific_obj_class is None:
134
135=== modified file 'src/lazr/json/version.txt'
136--- src/lazr/json/version.txt 2012-04-19 07:33:13 +0000
137+++ src/lazr/json/version.txt 2012-04-23 00:33:18 +0000
138@@ -1,1 +1,1 @@
139-0.1
140+0.2

Subscribers

People subscribed via source and target branches

to all changes: