1
"""Wraps the best available JSON implementation available in a common
7
__author__ = "Rune Halvorsen <runefh@gmail.com>"
8
__homepage__ = "http://bitbucket.org/runeh/anyjson/"
9
__docformat__ = "restructuredtext"
14
.. function:: serialize(obj)
16
Serialize the object to JSON.
18
.. function:: deserialize(str)
20
Deserialize JSON-encoded object to a Python object.
22
.. function:: force_implementation(name)
24
Load a specific json module. This is useful for testing and not much else
26
.. attribute:: implementation
28
The json implementation object. This is probably not useful to you,
29
except to get the name of the implementation in use. The name is
30
available through `implementation.name`.
34
List of known json modules, and the names of their serialize/unserialize
35
methods, as well as the exception they throw. Exception can be either
36
an exception class or a string.
38
_modules = [("cjson", "encode", "EncodeError", "decode", "DecodeError"),
39
("jsonlib2", "write", "WriteError", "read", "ReadError"),
40
("jsonlib", "write", "WriteError", "read", "ReadError"),
41
("simplejson", "dumps", TypeError, "loads", ValueError),
42
("json", "dumps", TypeError, "loads", ValueError),
43
("django.utils.simplejson", "dumps", TypeError, "loads",
45
_fields = ("modname", "encoder", "encerror", "decoder", "decerror")
48
class _JsonImplementation(object):
49
"""Incapsulates a JSON implementation"""
51
def __init__(self, modspec):
52
modinfo = dict(zip(_fields, modspec))
54
# No try block. We want importerror to end up at caller
55
module = self._attempt_load(modinfo["modname"])
57
self.implementation = modinfo["modname"]
58
self._encode = getattr(module, modinfo["encoder"])
59
self._decode = getattr(module, modinfo["decoder"])
60
self._encode_error = modinfo["encerror"]
61
self._decode_error = modinfo["decerror"]
63
if isinstance(modinfo["encerror"], basestring):
64
self._encode_error = getattr(module, modinfo["encerror"])
65
if isinstance(modinfo["decerror"], basestring):
66
self._decode_error = getattr(module, modinfo["decerror"])
68
self.name = modinfo["modname"]
71
return "<_JsonImplementation instance using %s>" % self.name
73
def _attempt_load(self, modname):
74
"""Attempt to load module name modname, returning it on success,
75
throwing ImportError if module couldn't be imported"""
77
return sys.modules[modname]
79
def serialize(self, data):
80
"""Serialize the datastructure to json. Returns a string. Raises
81
TypeError if the object could not be serialized."""
83
return self._encode(data)
84
except self._encode_error, exc:
85
raise TypeError(*exc.args)
87
def deserialize(self, s):
88
"""deserialize the string to python data types. Raises
89
ValueError if the string vould not be parsed."""
91
return self._decode(s)
92
except self._decode_error, exc:
93
raise ValueError(*exc.args)
96
def force_implementation(modname):
97
"""Forces anyjson to use a specific json module if it's available"""
99
for name, spec in [(e[0], e) for e in _modules]:
101
implementation = _JsonImplementation(spec)
103
raise ImportError("No module named: %s" % modname)
106
if __name__ == "__main__":
107
# If run as a script, we do nothing but print an error message.
108
# We do NOT try to load a compatible module because that may throw an
109
# exception, which renders the package uninstallable with easy_install
110
# (It trys to execfile the script when installing, to make sure it works)
111
print "Running anyjson as a stand alone script is not supported"
114
for modspec in _modules:
116
implementation = _JsonImplementation(modspec)
121
raise ImportError("No supported JSON module found")
123
serialize = lambda value: implementation.serialize(value)
124
deserialize = lambda value: implementation.deserialize(value)