diff options
Diffstat (limited to 'rest_framework/utils/encoders.py')
| -rw-r--r-- | rest_framework/utils/encoders.py | 87 |
1 files changed, 44 insertions, 43 deletions
diff --git a/rest_framework/utils/encoders.py b/rest_framework/utils/encoders.py index 00ffdfba..486186c9 100644 --- a/rest_framework/utils/encoders.py +++ b/rest_framework/utils/encoders.py @@ -2,12 +2,11 @@ Helper classes for parsers. """ from __future__ import unicode_literals -from django.utils import timezone 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 -from rest_framework.serializers import DictWithMetadata, SortedDictWithMetadata import datetime import decimal import types @@ -17,45 +16,47 @@ import json class JSONEncoder(json.JSONEncoder): """ JSONEncoder subclass that knows how to encode date/time/timedelta, - decimal types, and generators. + decimal types, generators and other basic python objects. """ - def default(self, o): + 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(o, Promise): - return force_text(o) - elif isinstance(o, datetime.datetime): - r = o.isoformat() - if o.microsecond: - r = r[:23] + r[26:] - if r.endswith('+00:00'): - r = r[:-6] + 'Z' - return r - elif isinstance(o, datetime.date): - return o.isoformat() - elif isinstance(o, datetime.time): - if timezone and timezone.is_aware(o): + if isinstance(obj, Promise): + return force_text(obj) + elif isinstance(obj, datetime.datetime): + representation = obj.isoformat() + if obj.microsecond: + representation = representation[:23] + representation[26:] + if representation.endswith('+00:00'): + representation = representation[:-6] + 'Z' + return representation + elif isinstance(obj, datetime.date): + return obj.isoformat() + elif isinstance(obj, datetime.time): + if timezone and timezone.is_aware(obj): raise ValueError("JSON can't represent timezone-aware times.") - r = o.isoformat() - if o.microsecond: - r = r[:12] - return r - elif isinstance(o, datetime.timedelta): - return str(o.total_seconds()) - elif isinstance(o, decimal.Decimal): - return str(o) - elif isinstance(o, QuerySet): - return list(o) - elif hasattr(o, 'tolist'): - return o.tolist() - elif hasattr(o, '__getitem__'): + representation = obj.isoformat() + if obj.microsecond: + representation = representation[:12] + return representation + elif isinstance(obj, datetime.timedelta): + return six.text_type(obj.total_seconds()) + elif isinstance(obj, decimal.Decimal): + # Serializers will coerce decimals to strings by default. + return float(obj) + elif isinstance(obj, QuerySet): + return tuple(obj) + elif hasattr(obj, 'tolist'): + # Numpy arrays and array scalars. + return obj.tolist() + elif hasattr(obj, '__getitem__'): try: - return dict(o) + return dict(obj) except: pass - elif hasattr(o, '__iter__'): - return [i for i in o] - return super(JSONEncoder, self).default(o) + elif hasattr(obj, '__iter__'): + return tuple(item for item in obj) + return super(JSONEncoder, self).default(obj) try: @@ -71,7 +72,7 @@ else: than the usual behaviour of sorting the keys. """ def represent_decimal(self, data): - return self.represent_scalar('tag:yaml.org,2002:str', str(data)) + return self.represent_scalar('tag:yaml.org,2002:str', six.text_type(data)) def represent_mapping(self, tag, mapping, flow_style=None): value = [] @@ -106,14 +107,14 @@ else: SortedDict, yaml.representer.SafeRepresenter.represent_dict ) - SafeDumper.add_representer( - DictWithMetadata, - yaml.representer.SafeRepresenter.represent_dict - ) - SafeDumper.add_representer( - SortedDictWithMetadata, - yaml.representer.SafeRepresenter.represent_dict - ) + # SafeDumper.add_representer( + # DictWithMetadata, + # yaml.representer.SafeRepresenter.represent_dict + # ) + # SafeDumper.add_representer( + # SortedDictWithMetadata, + # yaml.representer.SafeRepresenter.represent_dict + # ) SafeDumper.add_representer( types.GeneratorType, yaml.representer.SafeRepresenter.represent_list |
