This commit is contained in:
Omer Katz 2014-10-02 14:50:22 +00:00
commit 863f871df4
3 changed files with 46 additions and 21 deletions

View File

@ -310,3 +310,18 @@ except ImportError:
klass.__unicode__ = klass.__str__ klass.__unicode__ = klass.__str__
klass.__str__ = lambda self: self.__unicode__().encode('utf-8') klass.__str__ = lambda self: self.__unicode__().encode('utf-8')
return klass return klass
import sys
if sys.version_info >= (3, 3):
from functools import lru_cache
else:
try:
from backports.functools_lru_cache import lru_cache
except ImportError:
def lru_cache(maxsize=100, typed=False): # When the LRU cache decorator is not available replace with a stub.
def decorating_function(f):
def wrapper(*args, **kwargs):
return f(*args, **kwargs)
return wrapper
return decorating_function

View File

@ -111,7 +111,8 @@ DEFAULTS = {
'UNICODE_JSON': True, 'UNICODE_JSON': True,
'COMPACT_JSON': True, 'COMPACT_JSON': True,
'COERCE_DECIMAL_TO_STRING': True, 'COERCE_DECIMAL_TO_STRING': True,
'UPLOADED_FILES_USE_URL': True 'UPLOADED_FILES_USE_URL': True,
'ENCODER_LRU_CACHE_SIZE': 1024
} }

View File

@ -2,16 +2,19 @@
Helper classes for parsers. Helper classes for parsers.
""" """
from __future__ import unicode_literals from __future__ import unicode_literals
from django.db.models.query import QuerySet
from django.utils import six, timezone
from django.utils.datastructures import SortedDict
from django.utils.functional import Promise
from rest_framework.compat import force_text
import datetime import datetime
import decimal import decimal
import types import types
import json import json
from django.db.models.query import QuerySet
from django.utils import six, timezone
from django.utils.datastructures import SortedDict
from django.utils.functional import Promise
from rest_framework.compat import force_text, lru_cache
from rest_framework.settings import api_settings
class JSONEncoder(json.JSONEncoder): class JSONEncoder(json.JSONEncoder):
""" """
@ -19,11 +22,28 @@ class JSONEncoder(json.JSONEncoder):
decimal types, generators and other basic python objects. decimal types, generators and other basic python objects.
""" """
def default(self, obj): def default(self, obj):
# For Date Time string spec, see ECMA 262
# http://ecma-international.org/ecma-262/5.1/#sec-15.9.1.15
if isinstance(obj, Promise): if isinstance(obj, Promise):
return force_text(obj) return force_text(obj)
elif isinstance(obj, datetime.datetime): elif isinstance(obj, QuerySet):
return tuple(obj)
elif hasattr(obj, '__getitem__'):
try:
return dict(obj)
except:
pass
elif hasattr(obj, 'tolist'):
# Numpy arrays and array scalars.
return obj.tolist()
elif hasattr(obj, '__iter__'):
return tuple(item for item in obj)
return self._default(obj)
@lru_cache(typed=True, maxsize=api_settings.ENCODER_LRU_CACHE_SIZE)
def _default(self, obj):
# For Date Time string spec, see ECMA 262
# http://ecma-international.org/ecma-262/5.1/#sec-15.9.1.15
if isinstance(obj, datetime.datetime):
representation = obj.isoformat() representation = obj.isoformat()
if obj.microsecond: if obj.microsecond:
representation = representation[:23] + representation[26:] representation = representation[:23] + representation[26:]
@ -44,18 +64,7 @@ class JSONEncoder(json.JSONEncoder):
elif isinstance(obj, decimal.Decimal): elif isinstance(obj, decimal.Decimal):
# Serializers will coerce decimals to strings by default. # Serializers will coerce decimals to strings by default.
return float(obj) return float(obj)
elif isinstance(obj, QuerySet):
return list(obj)
elif hasattr(obj, 'tolist'):
# Numpy arrays and array scalars.
return obj.tolist()
elif hasattr(obj, '__getitem__'):
try:
return dict(obj)
except:
pass
elif hasattr(obj, '__iter__'):
return [item for item in obj]
return super(JSONEncoder, self).default(obj) return super(JSONEncoder, self).default(obj)