9

I'm using flask and have a lot of requests. The json module, which is used by flask, is quite slow. I automatically can use simplejson, but thats a bit slower, not faster. According to the documentation I can define a decoder (flask.json_decoder), but orjson doesn't have this class. I only have the function loads and dumps. Can somebody explain me, how I can exchange the json module with orjson? In the end I just want to use the loads and dumps function, but I can't connect my loose ends.

Stefan Berger
  • 133
  • 1
  • 10

2 Answers2

7

a very basic implementation could look like this:

class ORJSONDecoder:

    def __init__(self, **kwargs):
        # eventually take into consideration when deserializing
        self.options = kwargs

    def decode(self, obj):
        return orjson.loads(obj)


class ORJSONEncoder:

    def __init__(self, **kwargs):
        # eventually take into consideration when serializing
        self.options = kwargs

    def encode(self, obj):
        # decode back to str, as orjson returns bytes
        return orjson.dumps(obj).decode('utf-8')


app = Flask(__name__)
app.json_encoder = ORJSONEncoder
app.json_decoder = ORJSONDecoder
yedpodtrzitko
  • 9,035
  • 2
  • 40
  • 42
  • 1
    For the record: setting `json_decoder` will use it also for other internal Flask stuff. And due to the lack of `object_hook`, it subtly breaks e.g. session handling (I learned it the hard way when flash messages broke and I had to learn about Flask's tagged JSON to understand why). – hynek Aug 06 '21 at 12:27
  • https://flask.palletsprojects.com/en/2.0.x/api/#tagged-json – Thomas Grainger Aug 06 '21 at 12:32
  • Seems like a waste to decode the utf-8 string, given it will be written as bytes again to the wire. – Nate Glenn Apr 15 '22 at 00:39
6

Since version 2.2.0 of Flask you should use code like this:

from flask.json.provider import JSONProvider
from flask import Flask
import orjson


class ORJSONProvider(JSONProvider):
    def __init__(self, *args, **kwargs):
        self.options = kwargs
        super().__init__(*args, **kwargs)
    
    def loads(self, s, **kwargs):
        return orjson.loads(s)
    
    def dumps(self, obj, **kwargs):
        # decode back to str, as orjson returns bytes
        return orjson.dumps(obj, option=orjson.OPT_NON_STR_KEYS).decode('utf-8')


app = Flask(__name__)
app.json = ORJSONProvider(app)
schot
  • 10,958
  • 2
  • 46
  • 71