Commits

Armin Ronacher committed 05c6502

Let json.* work even without app on the stack and added tests

Comments (0)

Files changed (2)

 
 def dumps(obj, **kwargs):
     """Serialize ``obj`` to a JSON formatted ``str`` by using the application's
-    configured encoder (:attr:`~flask.Flask.json_encoder`).
+    configured encoder (:attr:`~flask.Flask.json_encoder`) if there is an
+    application on the stack.
     """
-    kwargs.setdefault('cls', current_app.json_encoder)
+    if current_app:
+        kwargs.setdefault('cls', current_app.json_encoder)
     return _json.dumps(obj, **kwargs)
 
 
 def dump(obj, fp, **kwargs):
     """Like :func:`dumps` but writes into a file object."""
-    kwargs.setdefault('cls', current_app.json_encoder)
+    if current_app:
+        kwargs.setdefault('cls', current_app.json_encoder)
     return _json.dump(obj, fp, **kwargs)
 
 
 def loads(s, **kwargs):
     """Unserialize a JSON object from a string ``s`` by using the application's
-    configured decoder (:attr:`~flask.Flask.json_decoder`).
+    configured decoder (:attr:`~flask.Flask.json_decoder`) if there is an
+    application on the stack.
     """
-    kwargs.setdefault('cls', current_app.json_decoder)
+    if current_app:
+        kwargs.setdefault('cls', current_app.json_decoder)
     return _json.loads(s, **kwargs)
 
 
 def load(fp, **kwargs):
     """Like :func:`loads` but reads from a file object.
     """
-    kwargs.setdefault('cls', current_app.json_decoder)
+    if current_app:
+        kwargs.setdefault('cls', current_app.json_decoder)
     return _json.load(fp, **kwargs)
 
 

flask/testsuite/helpers.py

             rv = render('{{ "<!--<script>"|tojson|safe }}')
             self.assert_equal(rv, '"<\\u0021--<script>"')
 
+    def test_json_customization(self):
+        class X(object):
+            def __init__(self, val):
+                self.val = val
+        class MyEncoder(flask.json.JSONEncoder):
+            def default(self, o):
+                if isinstance(o, X):
+                    return '<%d>' % o.val
+                return flask.json.JSONEncoder.default(self, o)
+        class MyDecoder(flask.json.JSONDecoder):
+            def __init__(self, *args, **kwargs):
+                kwargs.setdefault('object_hook', self.object_hook)
+                flask.json.JSONDecoder.__init__(self, *args, **kwargs)
+            def object_hook(self, obj):
+                if len(obj) == 1 and '_foo' in obj:
+                    return X(obj['_foo'])
+                return obj
+        app = flask.Flask(__name__)
+        app.testing = True
+        app.json_encoder = MyEncoder
+        app.json_decoder = MyDecoder
+        @app.route('/', methods=['POST'])
+        def index():
+            return flask.json.dumps(flask.request.json['x'])
+        c = app.test_client()
+        rv = c.post('/', data=flask.json.dumps({
+            'x': {'_foo': 42}
+        }), content_type='application/json')
+        self.assertEqual(rv.data, '"<42>"')
+
     def test_modified_url_encoding(self):
         class ModifiedRequest(flask.Request):
             url_charset = 'euc-kr'