This report is out-of-date.
The state of things has changed dramatically, for the better, since I first wrote this in early 2008. Although my test cases are still quite useful, any information regarding specific python packages is likely to be inaccurate. I am leaving these pages here primarily for historic interest.
Sequences
For these tests, the following Python definitions will be used:
# Generator def gen3(): yield 1; yield 2; yield 3 # Array import array arr = array.array('i', [1,2,3]) # Deque import collections deq = collections.deque() deq.append(1); deq.append(2); deq.append(3) # Default dict defdict = collections.defaultdict( lambda: 9 ) defdict["a"] = 42 # UserList import UserList ulist = UserList.UserList() ulist.append(1); ulist.append(2); ulist.append(3) # UserDict import UserDict udict = UserDict.UserDict() udict["a"] = 42 # Cyclic data structure cyclic = [42] cyclic.append( cyclic )
Converting Python sequences to JSON
Diversity of sequence and map types
These tests determine which standard Python collection or
sequence-like types can be automatically converted into a reasonable
JSON representation. Clearly all JSON modules must handle the builtin
list, tuple, and dict types;
with other types perhaps being less important. It is also
important that Python's str and unicode
types are never interpreted as being sequences for the purposes
of JSON output.
Both the demjson and simplejson modules have documented extension techniques to allow them to handle additional types that they may not be able to handle by default.
For unordered Python types such as set and
frozenset we do not necessarily care about the order (or
lack thereof) in which the elements are output in the generated JSON.
Similarly for dictionaries, the order in which dict items
are placed into JSON object members is also unimportant. Some modules
though may perform sorting by keys either by default (demjson),
or by caller option (jsonlib and simplejson).
| Test# | from Python | to JSON | demjson | jsonlib | python-cjson | python-json | simplejson |
|---|---|---|---|---|---|---|---|
| 1–1 | [] | [] | yes | yes | yes | yes | yes |
| 1–2 | () | [] | yes | yes | yes | yes | yes |
| 1–3 | {} | {} | yes | yes | yes | yes | yes |
| 1–4 | [1,2,3] | [1,2,3] | yes | yes | yes | yes | yes |
| 1–5 | (1,2,3) | [1,2,3] | yes | yes | yes | yes | yes |
| 1–6 | {"a":1} | {'a':1} | yes | yes | yes | yes | yes |
| 1–7 | set([1,5,10]) | [1,10,5] | yes | no | no | no | no |
| 1–8 | frozenset([1,5, 10]) |
[1,10,5] | yes | no | no | no | no |
| 1–9 | gen3() | [1,2,3] | yes | no | no | no | no |
| 1–10 | arr | [1,2,3] | yes | no | no | no | no |
| 1–11 | deq | [1,2,3] | yes | no | no | no | no |
| 1–12 | ulist | [1,2,3] | yes | no | no | no | no |
| 1–13 | defdict | {"a":42} | yes | no | yes | no | yes |
| 1–14 | udict | {"a":42} | yes | no | no | no | no |
Nesting depth
The next tests are used to determine the limits of nesting. JSON itself imposes no limit on how deeply objects can be nested, but allows implementations to do so. Some of the Python implementations have limits; particularly those that rely on recursion.
Notation:
The notation [...x...] means a nested
list which is x lists deep; e.g., [...3...] really means [[[]]].
On the system used for testing, the sys.getrecursionlimit() ==
1000. Also the testing framework used 2 additional stack
slots.
| Test# | from Python | to JSON | demjson | jsonlib | python-cjson | python-json | simplejson |
|---|---|---|---|---|---|---|---|
| 2–1 | [[]] | [[]] | yes | yes | yes | yes | yes |
| 2–2 | [[[]]] | [[[]]] | yes | yes | yes | yes | yes |
| 2–3 | [...497...] | [...497...] | yes | yes, but SLOW | yes | yes | yes |
| 2–4 | [...498...] | [...498...] | no | no | yes | yes | no |
| 2–5 | [...994...] | [...994...] | no | no | yes | yes | no |
| 2–6 | [...995...] | [...995...] | no | no | yes | no | no |
| 2–7 | [...5000...] | [...5000...] | no | no | yes | no | no |
Cyclic structure protection
In python it is possible to create cyclic data structures. Obviously these are not representable in JSON. However it may be desirable for a module attempting to convert such a cyclic object into JSON to abort with an error; it certainly should not get stuck in an infinite loop and ideally should not depend upon recursion stack exhaustion.
Note that the simplejson module performs cyclic structure detection by default, but it is possible to disable that feature (for performance) by invoking it as such:
# Disabling cycle detection in simplejson
json_ustr = simplejson.dumps( pyobject, check_circular=False )
Both demjson and python-cjson always perform cycle checks. The python-json module never does them, instead relying on the recusrion stack to overflow.
| Test# | from Python | to JSON | demjson | jsonlib | python-cjson | python-json | simplejson |
|---|---|---|---|---|---|---|---|
| 3–1 | cyclic | n/a | yes: raises JSONEncodeError | yes: raises jsonlib.errors.WriteError | yes: raises EncodeError | no: maximum recursion depth exceeded | yes: raises ValueError |

