Skip to content

Commit 3f8c4b6

Browse files
committed
Respect the json_provider_class
Respect the json_provider_class when available and stay compatible with flask < 2.2. Extended tox configuration to also test with flask < 2.2.
1 parent fcea059 commit 3f8c4b6

File tree

5 files changed

+46
-40
lines changed

5 files changed

+46
-40
lines changed

flask_jwt_extended/config.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from datetime import datetime
22
from datetime import timedelta
33
from datetime import timezone
4+
from json import JSONEncoder
45
from typing import Iterable
56
from typing import List
67
from typing import Optional
@@ -11,7 +12,7 @@
1112
from flask import current_app
1213
from jwt.algorithms import requires_cryptography
1314

14-
from flask_jwt_extended.json_encoder import JSONEncoder
15+
from flask_jwt_extended.internal_utils import get_json_encoder
1516
from flask_jwt_extended.typing import ExpiresDelta
1617

1718

@@ -284,7 +285,7 @@ def error_msg_key(self) -> str:
284285

285286
@property
286287
def json_encoder(self) -> Type[JSONEncoder]:
287-
return JSONEncoder
288+
return get_json_encoder(current_app)
288289

289290
@property
290291
def decode_audience(self) -> Union[str, Iterable[str]]:

flask_jwt_extended/internal_utils.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,25 @@
1+
import json
12
from typing import Any
3+
from typing import Type
24
from typing import TYPE_CHECKING
35

46
from flask import current_app
7+
from flask import Flask
58

69
from flask_jwt_extended.exceptions import RevokedTokenError
710
from flask_jwt_extended.exceptions import UserClaimsVerificationError
811
from flask_jwt_extended.exceptions import WrongTokenError
912

13+
try:
14+
from flask.json.provider import DefaultJSONProvider
15+
16+
HAS_JSON_PROVIDER = True
17+
except ModuleNotFoundError: # pragma: no cover
18+
# The flask.json.provider module was added in Flask 2.2.
19+
# Further details are handled in get_json_encoder.
20+
HAS_JSON_PROVIDER = False
21+
22+
1023
if TYPE_CHECKING: # pragma: no cover
1124
from flask_jwt_extended import JWTManager
1225

@@ -51,3 +64,31 @@ def custom_verification_for_token(jwt_header: dict, jwt_data: dict) -> None:
5164
if not jwt_manager._token_verification_callback(jwt_header, jwt_data):
5265
error_msg = "User claims verification failed"
5366
raise UserClaimsVerificationError(error_msg, jwt_header, jwt_data)
67+
68+
69+
def get_json_encoder(app: Flask) -> Type[json.JSONEncoder]:
70+
"""Get the JSON Encoder for the provided flask app
71+
72+
Starting with flask version 2.2 the flask application provides a
73+
interface to register a custom JSON Encoder/Decoder under the json_provider_class.
74+
As this interface is not compatible with the standard JSONEncoder, the `default`
75+
method of the class is wrapped.
76+
77+
Lookup Order:
78+
- app.json_encoder - For Flask < 2.2
79+
- app.json_provider_class.default
80+
- flask.json.provider.DefaultJSONProvider.default
81+
82+
"""
83+
if not HAS_JSON_PROVIDER: # pragma: no cover
84+
return app.json_encoder
85+
86+
# If the registered JSON provider does not implement a default classmethod
87+
# use the method defined by the DefaultJSONProvider
88+
default = getattr(app.json_provider_class, "default", DefaultJSONProvider.default)
89+
90+
class JSONEncoder(json.JSONEncoder):
91+
def default(self, o: Any) -> Any:
92+
return default(o) # pragma: no cover
93+
94+
return JSONEncoder

flask_jwt_extended/json_encoder.py

Lines changed: 0 additions & 36 deletions
This file was deleted.

flask_jwt_extended/tokens.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from datetime import timedelta
44
from datetime import timezone
55
from hmac import compare_digest
6+
from json import JSONEncoder
67
from typing import Any
78
from typing import Iterable
89
from typing import List
@@ -13,7 +14,6 @@
1314

1415
from flask_jwt_extended.exceptions import CSRFError
1516
from flask_jwt_extended.exceptions import JWTDecodeError
16-
from flask_jwt_extended.json_encoder import JSONEncoder
1717
from flask_jwt_extended.typing import ExpiresDelta
1818

1919

tox.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# and then run "tox" from this directory.
55

66
[tox]
7-
envlist = py37,py38,py39,py310,pypy3.9,mypy,coverage,style,docs
7+
envlist = py{37,38,39,310}-{flask21,flask22},pypy3.9,mypy,coverage,style,docs
88

99
[testenv]
1010
commands =

0 commit comments

Comments
 (0)