diff options
author | Antoine Pitrou <solipsis@pitrou.net> | 2010-11-04 16:51:32 (GMT) |
---|---|---|
committer | Antoine Pitrou <solipsis@pitrou.net> | 2010-11-04 16:51:32 (GMT) |
commit | 2397dd58b70986db898f689fe7a1597cdd51f29f (patch) | |
tree | dfbb92e9a134cc2bd9c9621a89a6bd9c17802128 | |
parent | 5ee89cf13ee8d1bfd2f56bca0432e23ba1009f1f (diff) | |
download | cpython-2397dd58b70986db898f689fe7a1597cdd51f29f.zip cpython-2397dd58b70986db898f689fe7a1597cdd51f29f.tar.gz cpython-2397dd58b70986db898f689fe7a1597cdd51f29f.tar.bz2 |
Issue #10314: improve performance of JSON encoding with sort_keys=True
-rw-r--r-- | Modules/_json.c | 45 |
1 files changed, 25 insertions, 20 deletions
diff --git a/Modules/_json.c b/Modules/_json.c index dd9749b..75b14ee 100644 --- a/Modules/_json.c +++ b/Modules/_json.c @@ -1387,8 +1387,6 @@ encoder_listencode_dict(PyEncoderObject *s, PyObject *rval, PyObject *dct, Py_ss PyObject *item = NULL; int skipkeys; Py_ssize_t idx; - PyObject *mapping; - static PyObject *code = NULL; if (open_dict == NULL || close_dict == NULL || empty_dict == NULL) { open_dict = PyUnicode_InternFromString("{"); @@ -1430,30 +1428,37 @@ encoder_listencode_dict(PyEncoderObject *s, PyObject *rval, PyObject *dct, Py_ss } if (PyObject_IsTrue(s->sort_keys)) { - if (code == NULL) { - code = Py_CompileString("sorted(d.items(), key=lambda kv: kv[0])", - "_json.c", Py_eval_input); - if (code == NULL) - goto bail; - } - - mapping = PyDict_New(); - if (mapping == NULL) + /* First sort the keys then replace them with (key, value) tuples. */ + Py_ssize_t i, nitems; + items = PyMapping_Keys(dct); + if (items == NULL) goto bail; - if (PyDict_SetItemString(mapping, "d", dct) == -1) { - Py_DECREF(mapping); + if (!PyList_Check(items)) { + PyErr_SetString(PyExc_ValueError, "keys must return list"); goto bail; } - items = PyEval_EvalCode((PyCodeObject *)code, PyEval_GetGlobals(), mapping); - Py_DECREF(mapping); - } else { - items = PyMapping_Items(dct); + if (PyList_Sort(items) < 0) + goto bail; + nitems = PyList_GET_SIZE(items); + 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; it = PyObject_GetIter(items); - Py_DECREF(items); - if (it == NULL) + Py_DECREF(items); + if (it == NULL) goto bail; skipkeys = PyObject_IsTrue(s->skipkeys); idx = 0; |