Skip to content

handle Decimal in json encoder #4157

@DougDK

Description

@DougDK

The simplejson removal (#3555) decreased the flask encoding capabilities as the built-in json doesn't cover cases like Decimal types. The solution seems to be: overwrite the flask app encoder with JSONEnconder from simplejson, but this incorporates a problem for users that relies on both Decimal and datetimes as simplejon doesn't handle datetimes, while flask encoder does. The solution I found is to build a custom encoder that tests if the value is Decimal and gives it to simplejson, otherwise, handles it with the default flask app encoder. My suggestion is to incorporate a simple test in the flask encoder to add Decimal coverage, that would remove any residual dependency on simplejson. The str(decimal) was taken from: simplejson/encoder.py#L511

from flask import json as fjson
from flask.json import JSONEncoder
import simplejson as sjson
import decimal
from datetime import datetime

rdatetime = datetime.strptime('1/1/2008 1:30 PM', '%m/%d/%Y %I:%M %p')
rdecimal = decimal.Decimal(10)

obj = {'datetime':rdatetime,'decimal':rdecimal}

fjson.dumps(obj) #Doesn't work because of decimal
sjson.dumps(obj) #Doesn't work because of datetimes

The custom encoder:

class CustomJSONEncoder(JSONEncoder):
    '''
    Add Decimal coverage
    '''
    def default(self, o):
        if isinstance(o, decimal.Decimal):
            return str(o)
        return super().default(o)

app.json_encoder = CustomJSONEncoder

The expected behavior is to work with both Decimal and datetimes as it used to work on Flask version 1.1.2

Environment:

  • Python version: 3.8.10
  • Flask version: 2.0.1 and 1.1.2
  • Simplejson(Optional) version: 3.17.2

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions