mirror of https://github.com/pallets/flask.git
173 lines
5.5 KiB
Python
173 lines
5.5 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""
|
|
flask.jsonimpl
|
|
~~~~~~~~~~~~~~
|
|
|
|
Implementation helpers for the JSON support in Flask.
|
|
|
|
:copyright: (c) 2012 by Armin Ronacher.
|
|
:license: BSD, see LICENSE for more details.
|
|
"""
|
|
import uuid
|
|
from datetime import datetime
|
|
from .globals import current_app, request
|
|
|
|
from werkzeug.http import http_date
|
|
|
|
# Use the same json implementation as itsdangerous on which we
|
|
# depend anyways.
|
|
from itsdangerous import simplejson as _json
|
|
import six
|
|
|
|
|
|
# figure out if simplejson escapes slashes. This behavior was changed
|
|
# from one version to another without reason.
|
|
_slash_escape = '\\/' not in _json.dumps('/')
|
|
|
|
|
|
__all__ = ['dump', 'dumps', 'load', 'loads', 'htmlsafe_dump',
|
|
'htmlsafe_dumps', 'JSONDecoder', 'JSONEncoder',
|
|
'jsonify']
|
|
|
|
|
|
class JSONEncoder(_json.JSONEncoder):
|
|
"""The default Flask JSON encoder. This one extends the default simplejson
|
|
encoder by also supporting ``datetime`` objects, ``UUID`` as well as
|
|
``Markup`` objects which are serialized as RFC 822 datetime strings (same
|
|
as the HTTP date format). In order to support more data types override the
|
|
:meth:`default` method.
|
|
"""
|
|
|
|
def default(self, o):
|
|
"""Implement this method in a subclass such that it returns a
|
|
serializable object for ``o``, or calls the base implementation (to
|
|
raise a ``TypeError``).
|
|
|
|
For example, to support arbitrary iterators, you could implement
|
|
default like this::
|
|
|
|
def default(self, o):
|
|
try:
|
|
iterable = iter(o)
|
|
except TypeError:
|
|
pass
|
|
else:
|
|
return list(iterable)
|
|
return JSONEncoder.default(self, o)
|
|
"""
|
|
if isinstance(o, datetime):
|
|
return http_date(o)
|
|
if isinstance(o, uuid.UUID):
|
|
return str(o)
|
|
if hasattr(o, '__html__'):
|
|
return six.text_type(o.__html__())
|
|
return _json.JSONEncoder.default(self, o)
|
|
|
|
|
|
class JSONDecoder(_json.JSONDecoder):
|
|
"""The default JSON decoder. This one does not change the behavior from
|
|
the default simplejson encoder. Consult the :mod:`json` documentation
|
|
for more information. This decoder is not only used for the load
|
|
functions of this module but also :attr:`~flask.Request`.
|
|
"""
|
|
|
|
|
|
def _dump_arg_defaults(kwargs):
|
|
"""Inject default arguments for dump functions."""
|
|
if current_app:
|
|
kwargs.setdefault('cls', current_app.json_encoder)
|
|
if not current_app.config['JSON_AS_ASCII']:
|
|
kwargs.setdefault('ensure_ascii', False)
|
|
|
|
|
|
def _load_arg_defaults(kwargs):
|
|
"""Inject default arguments for load functions."""
|
|
if current_app:
|
|
kwargs.setdefault('cls', current_app.json_decoder)
|
|
|
|
|
|
def dumps(obj, **kwargs):
|
|
"""Serialize ``obj`` to a JSON formatted ``str`` by using the application's
|
|
configured encoder (:attr:`~flask.Flask.json_encoder`) if there is an
|
|
application on the stack.
|
|
|
|
This function can return ``unicode`` strings or ascii-only bytestrings by
|
|
default which coerce into unicode strings automatically. That behavior by
|
|
default is controlled by the ``JSON_AS_ASCII`` configuration variable
|
|
and can be overriden by the simplejson ``ensure_ascii`` parameter.
|
|
"""
|
|
_dump_arg_defaults(kwargs)
|
|
return _json.dumps(obj, **kwargs)
|
|
|
|
|
|
def dump(obj, fp, **kwargs):
|
|
"""Like :func:`dumps` but writes into a file object."""
|
|
_dump_arg_defaults(kwargs)
|
|
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`) if there is an
|
|
application on the stack.
|
|
"""
|
|
_load_arg_defaults(kwargs)
|
|
return _json.loads(s, **kwargs)
|
|
|
|
|
|
def load(fp, **kwargs):
|
|
"""Like :func:`loads` but reads from a file object.
|
|
"""
|
|
_load_arg_defaults(kwargs)
|
|
return _json.load(fp, **kwargs)
|
|
|
|
|
|
def htmlsafe_dumps(obj, **kwargs):
|
|
"""Works exactly like :func:`dumps` but is safe for use in ``<script>``
|
|
tags. It accepts the same arguments and returns a JSON string. Note that
|
|
this is available in templates through the ``|tojson`` filter but it will
|
|
have to be wrapped in ``|safe`` unless **true** XHTML is being used.
|
|
"""
|
|
rv = dumps(obj, **kwargs)
|
|
if _slash_escape:
|
|
rv = rv.replace('/', '\\/')
|
|
return rv.replace('<!', '<\\u0021')
|
|
|
|
|
|
def htmlsafe_dump(obj, fp, **kwargs):
|
|
"""Like :func:`htmlsafe_dumps` but writes into a file object."""
|
|
fp.write(htmlsafe_dumps(obj, **kwargs))
|
|
|
|
|
|
def jsonify(*args, **kwargs):
|
|
"""Creates a :class:`~flask.Response` with the JSON representation of
|
|
the given arguments with an `application/json` mimetype. The arguments
|
|
to this function are the same as to the :class:`dict` constructor.
|
|
|
|
Example usage::
|
|
|
|
from flask import jsonify
|
|
|
|
@app.route('/_get_current_user')
|
|
def get_current_user():
|
|
return jsonify(username=g.user.username,
|
|
email=g.user.email,
|
|
id=g.user.id)
|
|
|
|
This will send a JSON response like this to the browser::
|
|
|
|
{
|
|
"username": "admin",
|
|
"email": "admin@localhost",
|
|
"id": 42
|
|
}
|
|
|
|
For security reasons only objects are supported toplevel. For more
|
|
information about this, have a look at :ref:`json-security`.
|
|
|
|
.. versionadded:: 0.2
|
|
"""
|
|
return current_app.response_class(dumps(dict(*args, **kwargs),
|
|
indent=None if request.is_xhr else 2),
|
|
mimetype='application/json')
|