Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit bcf6f92

Browse files
committed
* Fix-up a TODO (support the sort_key option).
* Fix an error where True/False were being written-out as title-cased strings when used a dictionary keys. * Speed-up iteration over dicts by looping over items() rather than keys() followed by value lookups. * TODO: sort only by keys, not keys and values.
1 parent 81c0dce commit bcf6f92

3 files changed

Lines changed: 46 additions & 21 deletions

File tree

Lib/json/encoder.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ def floatstr(o, allow_nan=self.allow_nan,
233233

234234

235235
if (_one_shot and c_make_encoder is not None
236-
and not self.indent and not self.sort_keys):
236+
and not self.indent):
237237
_iterencode = c_make_encoder(
238238
markers, self.default, _encoder, self.indent,
239239
self.key_separator, self.item_separator, self.sort_keys,

Lib/json/tests/test_encode_basestring_ascii.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,8 @@ def test_ordered_dict(self):
4343
items = [('one', 1), ('two', 2), ('three', 3), ('four', 4), ('five', 5)]
4444
s = json.dumps(OrderedDict(items))
4545
self.assertEqual(s, '{"one": 1, "two": 2, "three": 3, "four": 4, "five": 5}')
46+
47+
def test_sorted_dict(self):
48+
items = [('one', 1), ('two', 2), ('three', 3), ('four', 4), ('five', 5)]
49+
s = json.dumps(dict(items), sort_keys=True)
50+
self.assertEqual(s, '{"five": 5, "four": 4, "one": 1, "three": 3, "two": 2}')

Modules/_json.c

Lines changed: 40 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1334,9 +1334,9 @@ encoder_listencode_dict(PyEncoderObject *s, PyObject *rval, PyObject *dct, Py_ss
13341334
static PyObject *empty_dict = NULL;
13351335
PyObject *kstr = NULL;
13361336
PyObject *ident = NULL;
1337-
PyObject *key = NULL;
1338-
PyObject *value = NULL;
13391337
PyObject *it = NULL;
1338+
PyObject *items;
1339+
PyObject *item = NULL;
13401340
int skipkeys;
13411341
Py_ssize_t idx;
13421342

@@ -1379,16 +1379,38 @@ encoder_listencode_dict(PyEncoderObject *s, PyObject *rval, PyObject *dct, Py_ss
13791379
*/
13801380
}
13811381

1382-
/* TODO: C speedup not implemented for sort_keys */
1382+
items = PyObject_CallMethod(dct, "items", ""); /* XXX key=itemgetter(0) */
1383+
if (items == NULL)
1384+
goto bail;
1385+
if (PyObject_IsTrue(s->sort_keys)) {
1386+
PyObject *rv;
1387+
PyObject *itemlist;
1388+
1389+
itemlist = PySequence_List(items);
1390+
Py_DECREF(items);
1391+
if (itemlist == NULL)
1392+
goto bail;
13831393

1384-
it = PyObject_GetIter(dct);
1385-
if (it == NULL)
1394+
rv = PyObject_CallMethod(itemlist, "sort", "");
1395+
if (rv == NULL) {
1396+
Py_DECREF(itemlist);
1397+
goto bail;
1398+
}
1399+
items = itemlist;
1400+
}
1401+
it = PyObject_GetIter(items);
1402+
Py_DECREF(items);
1403+
if (it == NULL)
13861404
goto bail;
13871405
skipkeys = PyObject_IsTrue(s->skipkeys);
13881406
idx = 0;
1389-
while ((key = PyIter_Next(it)) != NULL) {
1390-
PyObject *encoded;
1391-
1407+
while ((item = PyIter_Next(it)) != NULL) {
1408+
PyObject *encoded, *key, *value;
1409+
if (!PyTuple_Check(item) || Py_SIZE(item) != 2) {
1410+
PyErr_SetString(PyExc_ValueError, "items must return 2-tuples");
1411+
goto bail;
1412+
}
1413+
key = PyTuple_GET_ITEM(item, 0);
13921414
if (PyUnicode_Check(key)) {
13931415
Py_INCREF(key);
13941416
kstr = key;
@@ -1398,18 +1420,20 @@ encoder_listencode_dict(PyEncoderObject *s, PyObject *rval, PyObject *dct, Py_ss
13981420
if (kstr == NULL)
13991421
goto bail;
14001422
}
1401-
else if (PyLong_Check(key)) {
1402-
kstr = PyObject_Str(key);
1423+
else if (key == Py_True || key == Py_False || key == Py_None) {
1424+
/* This must come before the PyLong_Check because
1425+
True and False are also 1 and 0.*/
1426+
kstr = _encoded_const(key);
14031427
if (kstr == NULL)
14041428
goto bail;
14051429
}
1406-
else if (key == Py_True || key == Py_False || key == Py_None) {
1407-
kstr = _encoded_const(key);
1430+
else if (PyLong_Check(key)) {
1431+
kstr = PyObject_Str(key);
14081432
if (kstr == NULL)
14091433
goto bail;
14101434
}
14111435
else if (skipkeys) {
1412-
Py_DECREF(key);
1436+
Py_DECREF(item);
14131437
continue;
14141438
}
14151439
else {
@@ -1435,14 +1459,11 @@ encoder_listencode_dict(PyEncoderObject *s, PyObject *rval, PyObject *dct, Py_ss
14351459
if (PyList_Append(rval, s->key_separator))
14361460
goto bail;
14371461

1438-
value = PyObject_GetItem(dct, key);
1439-
if (value == NULL)
1440-
goto bail;
1462+
value = PyTuple_GET_ITEM(item, 1);
14411463
if (encoder_listencode_obj(s, rval, value, indent_level))
14421464
goto bail;
14431465
idx += 1;
1444-
Py_CLEAR(value);
1445-
Py_DECREF(key);
1466+
Py_DECREF(item);
14461467
}
14471468
if (PyErr_Occurred())
14481469
goto bail;
@@ -1466,8 +1487,7 @@ encoder_listencode_dict(PyEncoderObject *s, PyObject *rval, PyObject *dct, Py_ss
14661487

14671488
bail:
14681489
Py_XDECREF(it);
1469-
Py_XDECREF(key);
1470-
Py_XDECREF(value);
1490+
Py_XDECREF(item);
14711491
Py_XDECREF(kstr);
14721492
Py_XDECREF(ident);
14731493
return -1;

0 commit comments

Comments
 (0)