* 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.
This commit is contained in:
parent
81c0dcee65
commit
bcf6f92dc5
|
@ -233,7 +233,7 @@ class JSONEncoder(object):
|
||||||
|
|
||||||
|
|
||||||
if (_one_shot and c_make_encoder is not None
|
if (_one_shot and c_make_encoder is not None
|
||||||
and not self.indent and not self.sort_keys):
|
and not self.indent):
|
||||||
_iterencode = c_make_encoder(
|
_iterencode = c_make_encoder(
|
||||||
markers, self.default, _encoder, self.indent,
|
markers, self.default, _encoder, self.indent,
|
||||||
self.key_separator, self.item_separator, self.sort_keys,
|
self.key_separator, self.item_separator, self.sort_keys,
|
||||||
|
|
|
@ -43,3 +43,8 @@ class TestEncodeBaseStringAscii(TestCase):
|
||||||
items = [('one', 1), ('two', 2), ('three', 3), ('four', 4), ('five', 5)]
|
items = [('one', 1), ('two', 2), ('three', 3), ('four', 4), ('five', 5)]
|
||||||
s = json.dumps(OrderedDict(items))
|
s = json.dumps(OrderedDict(items))
|
||||||
self.assertEqual(s, '{"one": 1, "two": 2, "three": 3, "four": 4, "five": 5}')
|
self.assertEqual(s, '{"one": 1, "two": 2, "three": 3, "four": 4, "five": 5}')
|
||||||
|
|
||||||
|
def test_sorted_dict(self):
|
||||||
|
items = [('one', 1), ('two', 2), ('three', 3), ('four', 4), ('five', 5)]
|
||||||
|
s = json.dumps(dict(items), sort_keys=True)
|
||||||
|
self.assertEqual(s, '{"five": 5, "four": 4, "one": 1, "three": 3, "two": 2}')
|
||||||
|
|
|
@ -1334,9 +1334,9 @@ encoder_listencode_dict(PyEncoderObject *s, PyObject *rval, PyObject *dct, Py_ss
|
||||||
static PyObject *empty_dict = NULL;
|
static PyObject *empty_dict = NULL;
|
||||||
PyObject *kstr = NULL;
|
PyObject *kstr = NULL;
|
||||||
PyObject *ident = NULL;
|
PyObject *ident = NULL;
|
||||||
PyObject *key = NULL;
|
|
||||||
PyObject *value = NULL;
|
|
||||||
PyObject *it = NULL;
|
PyObject *it = NULL;
|
||||||
|
PyObject *items;
|
||||||
|
PyObject *item = NULL;
|
||||||
int skipkeys;
|
int skipkeys;
|
||||||
Py_ssize_t idx;
|
Py_ssize_t idx;
|
||||||
|
|
||||||
|
@ -1379,16 +1379,38 @@ encoder_listencode_dict(PyEncoderObject *s, PyObject *rval, PyObject *dct, Py_ss
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: C speedup not implemented for sort_keys */
|
items = PyObject_CallMethod(dct, "items", ""); /* XXX key=itemgetter(0) */
|
||||||
|
if (items == NULL)
|
||||||
|
goto bail;
|
||||||
|
if (PyObject_IsTrue(s->sort_keys)) {
|
||||||
|
PyObject *rv;
|
||||||
|
PyObject *itemlist;
|
||||||
|
|
||||||
|
itemlist = PySequence_List(items);
|
||||||
|
Py_DECREF(items);
|
||||||
|
if (itemlist == NULL)
|
||||||
|
goto bail;
|
||||||
|
|
||||||
it = PyObject_GetIter(dct);
|
rv = PyObject_CallMethod(itemlist, "sort", "");
|
||||||
if (it == NULL)
|
if (rv == NULL) {
|
||||||
|
Py_DECREF(itemlist);
|
||||||
|
goto bail;
|
||||||
|
}
|
||||||
|
items = itemlist;
|
||||||
|
}
|
||||||
|
it = PyObject_GetIter(items);
|
||||||
|
Py_DECREF(items);
|
||||||
|
if (it == NULL)
|
||||||
goto bail;
|
goto bail;
|
||||||
skipkeys = PyObject_IsTrue(s->skipkeys);
|
skipkeys = PyObject_IsTrue(s->skipkeys);
|
||||||
idx = 0;
|
idx = 0;
|
||||||
while ((key = PyIter_Next(it)) != NULL) {
|
while ((item = PyIter_Next(it)) != NULL) {
|
||||||
PyObject *encoded;
|
PyObject *encoded, *key, *value;
|
||||||
|
if (!PyTuple_Check(item) || Py_SIZE(item) != 2) {
|
||||||
|
PyErr_SetString(PyExc_ValueError, "items must return 2-tuples");
|
||||||
|
goto bail;
|
||||||
|
}
|
||||||
|
key = PyTuple_GET_ITEM(item, 0);
|
||||||
if (PyUnicode_Check(key)) {
|
if (PyUnicode_Check(key)) {
|
||||||
Py_INCREF(key);
|
Py_INCREF(key);
|
||||||
kstr = key;
|
kstr = key;
|
||||||
|
@ -1398,18 +1420,20 @@ encoder_listencode_dict(PyEncoderObject *s, PyObject *rval, PyObject *dct, Py_ss
|
||||||
if (kstr == NULL)
|
if (kstr == NULL)
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
|
else if (key == Py_True || key == Py_False || key == Py_None) {
|
||||||
|
/* This must come before the PyLong_Check because
|
||||||
|
True and False are also 1 and 0.*/
|
||||||
|
kstr = _encoded_const(key);
|
||||||
|
if (kstr == NULL)
|
||||||
|
goto bail;
|
||||||
|
}
|
||||||
else if (PyLong_Check(key)) {
|
else if (PyLong_Check(key)) {
|
||||||
kstr = PyObject_Str(key);
|
kstr = PyObject_Str(key);
|
||||||
if (kstr == NULL)
|
if (kstr == NULL)
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
else if (key == Py_True || key == Py_False || key == Py_None) {
|
|
||||||
kstr = _encoded_const(key);
|
|
||||||
if (kstr == NULL)
|
|
||||||
goto bail;
|
|
||||||
}
|
|
||||||
else if (skipkeys) {
|
else if (skipkeys) {
|
||||||
Py_DECREF(key);
|
Py_DECREF(item);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -1435,14 +1459,11 @@ encoder_listencode_dict(PyEncoderObject *s, PyObject *rval, PyObject *dct, Py_ss
|
||||||
if (PyList_Append(rval, s->key_separator))
|
if (PyList_Append(rval, s->key_separator))
|
||||||
goto bail;
|
goto bail;
|
||||||
|
|
||||||
value = PyObject_GetItem(dct, key);
|
value = PyTuple_GET_ITEM(item, 1);
|
||||||
if (value == NULL)
|
|
||||||
goto bail;
|
|
||||||
if (encoder_listencode_obj(s, rval, value, indent_level))
|
if (encoder_listencode_obj(s, rval, value, indent_level))
|
||||||
goto bail;
|
goto bail;
|
||||||
idx += 1;
|
idx += 1;
|
||||||
Py_CLEAR(value);
|
Py_DECREF(item);
|
||||||
Py_DECREF(key);
|
|
||||||
}
|
}
|
||||||
if (PyErr_Occurred())
|
if (PyErr_Occurred())
|
||||||
goto bail;
|
goto bail;
|
||||||
|
@ -1466,8 +1487,7 @@ encoder_listencode_dict(PyEncoderObject *s, PyObject *rval, PyObject *dct, Py_ss
|
||||||
|
|
||||||
bail:
|
bail:
|
||||||
Py_XDECREF(it);
|
Py_XDECREF(it);
|
||||||
Py_XDECREF(key);
|
Py_XDECREF(item);
|
||||||
Py_XDECREF(value);
|
|
||||||
Py_XDECREF(kstr);
|
Py_XDECREF(kstr);
|
||||||
Py_XDECREF(ident);
|
Py_XDECREF(ident);
|
||||||
return -1;
|
return -1;
|
||||||
|
|
Loading…
Reference in New Issue