88 lines
3.1 KiB
Python
88 lines
3.1 KiB
Python
import json
|
|
from datetime import date
|
|
from email.utils import formatdate
|
|
from time import mktime
|
|
from typing import Any, TYPE_CHECKING
|
|
from uuid import UUID
|
|
|
|
from jinja2 import Markup
|
|
|
|
from ..globals import _app_ctx_stack, _request_ctx_stack, current_app, request
|
|
|
|
if TYPE_CHECKING:
|
|
from ..wrappers import Response # noqa: F401
|
|
|
|
|
|
def dumps(object_: Any, **kwargs: Any) -> str:
|
|
json_encoder = JSONEncoder
|
|
if _app_ctx_stack.top is not None: # has_app_context requires a circular import
|
|
json_encoder = current_app.json_encoder
|
|
if _request_ctx_stack.top is not None: # has_request_context requires a circular import
|
|
blueprint = current_app.blueprints.get(request.blueprint)
|
|
if blueprint is not None and blueprint.json_encoder is not None:
|
|
json_encoder = blueprint.json_encoder
|
|
kwargs.setdefault('ensure_ascii', current_app.config['JSON_AS_ASCII'])
|
|
kwargs.setdefault('sort_keys', current_app.config['JSON_SORT_KEYS'])
|
|
kwargs.setdefault('sort_keys', True)
|
|
kwargs.setdefault('cls', json_encoder)
|
|
|
|
return json.dumps(object_, **kwargs)
|
|
|
|
|
|
def loads(object_: Any, **kwargs: Any) -> str:
|
|
json_decoder = JSONDecoder
|
|
if _app_ctx_stack.top is not None: # has_app_context requires a circular import
|
|
json_decoder = current_app.json_decoder
|
|
if _request_ctx_stack.top is not None: # has_request_context requires a circular import
|
|
blueprint = current_app.blueprints.get(request.blueprint)
|
|
if blueprint is not None and blueprint.json_decoder is not None:
|
|
json_decoder = blueprint.json_decoder
|
|
kwargs.setdefault('cls', json_decoder)
|
|
|
|
return json.loads(object_, **kwargs)
|
|
|
|
|
|
def htmlsafe_dumps(object_: Any, **kwargs: Any) -> str:
|
|
# Note in the below the ascii characters are replaced with a
|
|
# unicode similar version.
|
|
result = dumps(object_, **kwargs).replace('<', '<').replace('>', '>')
|
|
return result.replace('&', '&').replace("'", "'")
|
|
|
|
|
|
def tojson_filter(object_: Any, **kwargs: Any) -> Markup:
|
|
return Markup(htmlsafe_dumps(object_, **kwargs))
|
|
|
|
|
|
def jsonify(*args: Any, **kwargs: Any) -> 'Response':
|
|
if args and kwargs:
|
|
raise TypeError('jsonify() behavior undefined when passed both args and kwargs')
|
|
elif len(args) == 1:
|
|
data = args[0]
|
|
else:
|
|
data = args or kwargs
|
|
|
|
indent = None
|
|
separators = (',', ':')
|
|
if current_app.config['JSONIFY_PRETTYPRINT_REGULAR'] or current_app.debug:
|
|
indent = 2
|
|
separators = (', ', ': ')
|
|
|
|
body = dumps(data, indent=indent, separators=separators)
|
|
return current_app.response_class(body, content_type=current_app.config['JSONIFY_MIMETYPE'])
|
|
|
|
|
|
class JSONEncoder(json.JSONEncoder):
|
|
|
|
def default(self, object_: Any) -> Any:
|
|
if isinstance(object_, date):
|
|
return formatdate(timeval=mktime((object_.timetuple())), localtime=False, usegmt=True)
|
|
if isinstance(object_, UUID):
|
|
return str(object_)
|
|
if hasattr(object_, '__html__'):
|
|
return str(object_.__html__())
|
|
return super().default(object_)
|
|
|
|
|
|
class JSONDecoder(json.JSONDecoder):
|
|
pass
|