Commit 2397dd58 authored by Antoine Pitrou's avatar Antoine Pitrou

Issue #10314: improve performance of JSON encoding with sort_keys=True

parent 5ee89cf1
...@@ -1387,8 +1387,6 @@ encoder_listencode_dict(PyEncoderObject *s, PyObject *rval, PyObject *dct, Py_ss ...@@ -1387,8 +1387,6 @@ encoder_listencode_dict(PyEncoderObject *s, PyObject *rval, PyObject *dct, Py_ss
PyObject *item = NULL; PyObject *item = NULL;
int skipkeys; int skipkeys;
Py_ssize_t idx; Py_ssize_t idx;
PyObject *mapping;
static PyObject *code = NULL;
if (open_dict == NULL || close_dict == NULL || empty_dict == NULL) { if (open_dict == NULL || close_dict == NULL || empty_dict == NULL) {
open_dict = PyUnicode_InternFromString("{"); open_dict = PyUnicode_InternFromString("{");
...@@ -1430,30 +1428,37 @@ encoder_listencode_dict(PyEncoderObject *s, PyObject *rval, PyObject *dct, Py_ss ...@@ -1430,30 +1428,37 @@ encoder_listencode_dict(PyEncoderObject *s, PyObject *rval, PyObject *dct, Py_ss
} }
if (PyObject_IsTrue(s->sort_keys)) { if (PyObject_IsTrue(s->sort_keys)) {
if (code == NULL) { /* First sort the keys then replace them with (key, value) tuples. */
code = Py_CompileString("sorted(d.items(), key=lambda kv: kv[0])", Py_ssize_t i, nitems;
"_json.c", Py_eval_input); items = PyMapping_Keys(dct);
if (code == NULL) if (items == NULL)
goto bail;
}
mapping = PyDict_New();
if (mapping == NULL)
goto bail; goto bail;
if (PyDict_SetItemString(mapping, "d", dct) == -1) { if (!PyList_Check(items)) {
Py_DECREF(mapping); PyErr_SetString(PyExc_ValueError, "keys must return list");
goto bail; goto bail;
} }
items = PyEval_EvalCode((PyCodeObject *)code, PyEval_GetGlobals(), mapping); if (PyList_Sort(items) < 0)
Py_DECREF(mapping); goto bail;
} else { nitems = PyList_GET_SIZE(items);
items = PyMapping_Items(dct); for (i = 0; i < nitems; i++) {
PyObject *key, *value;
key = PyList_GET_ITEM(items, i);
value = PyDict_GetItem(dct, key);
item = PyTuple_Pack(2, key, value);
if (item == NULL)
goto bail;
PyList_SET_ITEM(items, i, item);
Py_DECREF(key);
} }
if (items == NULL) }
else {
items = PyMapping_Items(dct);
}
if (items == NULL)
goto bail; goto bail;
it = PyObject_GetIter(items); it = PyObject_GetIter(items);
Py_DECREF(items); Py_DECREF(items);
if (it == NULL) if (it == NULL)
goto bail; goto bail;
skipkeys = PyObject_IsTrue(s->skipkeys); skipkeys = PyObject_IsTrue(s->skipkeys);
idx = 0; idx = 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment