JSON Date and Datetime serialization and deserialization


I know I can just json.dumps(obj, default=date_handler) and just move on with life, but one of the things I really liked about flask.json module was the framework support for JSON. I can’t seem to find anything in this forum related to these convenience utilities. Does anyone have any thoughts on these features being in the framework?


There will be proper incoming support here, yup. Needs some work both on the typesystem (have an equivelent to JSON Schemas “format” attribute on string-serializable data types) and some tweaking on how we render the final responses.


Awesome, glad to hear it! For now I will just have to be content with some of the other workarounds for ISO 8601 date formats.

What about support for XML as a response Content-Type? I can drop into the WSGI layer for this, but when looking at Flask-Eve they support Content-Type negotiation with either XML or JSON as out of the box formats.


We’ll have something very similar to REST framework’s configurable parsers/renderers, yup.


How are you doing this now.

I want to achieve the following and am having trouble:

  • Output datetime objects (convert to ISO8601)
  • Output UTF8 encoded text (as provided by ensure_ascii=False)

Currently, with apistar, I’m trying to format datetime and pass the resulting pre-formatted JSON string to the Response object, but when I do this, it escapes the JSON.

Then if I try to work around by reloading the JSON to a dict and give that to the Response() object, I don’t get the UTF8 output displayed (as is provided by ensure_ascii=False).

dumped_json = json.dumps(data,
reloaded_json = json.loads(dumped_json)
return Response(reloaded_json, status=200, headers={})

I suppose I can just convert the datetime to string… but how can I get the UTF8 encoded text to be output? Is there a ensure_ascii=False similar option available?


I achieved this by first writing a function that resolves handing the datetime and decimal types to a compatible JSON type

def encoder(obj):
        """JSON encoder function for datetime and decimal."""
        if isinstance(obj, dt.datetime):
            return obj.isoformat()
        elif isinstance(obj, decimal.Decimal):
            return float(obj)

Then I I just wrote my own JSONRender and substituted that for the default JSONRender.

from apistar.renderers import Renderer

class JSONRenderer(Renderer):
    media_type = 'application/json'
    charset = None

    def render(self, data: http.ResponseData) -> bytes:
        return json.dumps(data, default=encoder).encode('utf-8')


How is the Renderer registered or specified to be used?


You pass an instance of your render in the settings. It’s pretty well documented on the README. This overrides the default render. Or you can annotate all your view functions, but I typically just use it globally.