pallets/flask

jsonify does not support integer keys

theiosif opened this issue · 1 comments

The snippets below are self-descriptive and reflect the problem mentioned in the title.

Expected behavior: jsonify builds a response irrespective of the key/value data types (at least for basic types like int and str)

Actual behavior: keys of type int break jsonify

Personal suggestion: just typecast to str, but issue a warning

Minimal code to reproduce the issue:

from flask import Flask, jsonify
import json

d={32: "aa", "something":"else"}

print(json.dumps(d)) # works # <-------

app = Flask('app')

# app.config['JSON_SORT_KEYS'] = False  #<-- makes no difference

with app.app_context():
    print(jsonify(d)) # b0rks # <-------

Error log:

TypeError                                 Traceback (most recent call last)
<ipython-input-12-d8fbf48063d9> in <module>
      1 with app.app_context():
----> 2     jsonify(d)
      3

~/.local/lib/python3.10/site-packages/flask/json/__init__.py in jsonify(*args, **kwargs)
    168     .. versionadded:: 0.2
    169     """
--> 170     return current_app.json.response(*args, **kwargs)

~/.local/lib/python3.10/site-packages/flask/json/provider.py in response(self, *args, **kwargs)
    213
    214         return self._app.response_class(
--> 215             f"{self.dumps(obj, **dump_args)}\n", mimetype=self.mimetype
    216         )

~/.local/lib/python3.10/site-packages/flask/json/provider.py in dumps(self, obj, **kwargs)
    178         kwargs.setdefault("ensure_ascii", self.ensure_ascii)
    179         kwargs.setdefault("sort_keys", self.sort_keys)
--> 180         return json.dumps(obj, **kwargs)
    181
    182     def loads(self, s: str | bytes, **kwargs: t.Any) -> t.Any:

/usr/lib/python3.10/json/__init__.py in dumps(obj, skipkeys, ensure_ascii, check_circular, allow_nan, cls, indent, separators, default, sort_keys, **kw)
    236         check_circular=check_circular, allow_nan=allow_nan, indent=indent,
    237         separators=separators, default=default, sort_keys=sort_keys,
--> 238         **kw).encode(obj)
    239
    240

/usr/lib/python3.10/json/encoder.py in encode(self, o)
    197         # exceptions aren't as detailed.  The list call should be roughly
    198         # equivalent to the PySequence_Fast that ''.join() would do.
--> 199         chunks = self.iterencode(o, _one_shot=True)
    200         if not isinstance(chunks, (list, tuple)):
    201             chunks = list(chunks)

/usr/lib/python3.10/json/encoder.py in iterencode(self, o, _one_shot)
    255                 self.key_separator, self.item_separator, self.sort_keys,
    256                 self.skipkeys, _one_shot)
--> 257         return _iterencode(o, 0)
    258
    259 def _make_iterencode(markers, _default, _encoder, _indent, _floatstr,

TypeError: '<' not supported between instances of 'str' and 'int'
  • Python version: Python 3.10.12
  • Flask version: Flask 2.3.3
  • Werkzeug 2.3.7

If you have data that is not serializable to JSON, you'll need to process that data first. Libraries like Marshmallow, attrs/cattrs, Pydantic, and others, are available that can do that.