summaryrefslogtreecommitdiff
path: root/pecan/jsonify.py
diff options
context:
space:
mode:
Diffstat (limited to 'pecan/jsonify.py')
-rw-r--r--pecan/jsonify.py65
1 files changed, 65 insertions, 0 deletions
diff --git a/pecan/jsonify.py b/pecan/jsonify.py
new file mode 100644
index 0000000..128e3bb
--- /dev/null
+++ b/pecan/jsonify.py
@@ -0,0 +1,65 @@
+from simplejson import JSONEncoder, dumps
+from datetime import datetime, date
+from decimal import Decimal
+from webob.multidict import MultiDict
+from simplegeneric import generic
+
+
+#
+# exceptions
+#
+
+class JsonEncodeError(Exception):
+ pass
+
+
+#
+# encoders
+#
+
+class BaseEncoder(JSONEncoder):
+ def is_saobject(self, obj):
+ return hasattr(obj, '_sa_class_manager')
+
+ def jsonify(self, obj):
+ return dumps(self.encode(obj))
+
+ def encode(self, obj):
+ if hasattr(obj, '__json__') and callable(obj.__json__):
+ return obj.__json__()
+ elif isinstance(obj, (date, datetime)):
+ return str(obj)
+ elif isinstance(obj, Decimal):
+ return float(obj)
+ elif self.is_saobject(obj):
+ props = {}
+ for key in obj.__dict__:
+ if not key.startswith('_sa_'):
+ props[key] = getattr(obj, key)
+ return props
+ elif isinstance(obj, MultiDict):
+ return obj.mixed()
+ else:
+ try:
+ from sqlalchemy.engine.base import ResultProxy, RowProxy
+ if isinstance(obj, ResultProxy):
+ return dict(rows=list(obj), count=obj.rowcount)
+ elif isinstance(obj, RowProxy):
+ return dict(rows=dict(obj), count=1)
+ except:
+ pass
+ return obj
+
+
+#
+# generic function support
+#
+
+encoder = BaseEncoder()
+
+@generic
+def jsonify(obj):
+ return encoder.encode(obj)
+
+def encode(obj):
+ return dumps(jsonify(obj)) \ No newline at end of file