mirror of https://github.com/python/cpython
Backport r72961 fixing issue #6105: json.dumps not following OrderedDict iteration order.
This commit is contained in:
parent
5306234655
commit
cbba8d4c7a
|
@ -1,6 +1,8 @@
|
|||
from unittest import TestCase
|
||||
|
||||
import json.encoder
|
||||
from json import dumps
|
||||
from collections import OrderedDict
|
||||
|
||||
CASES = [
|
||||
(u'/\\"\ucafe\ubabe\uab98\ufcde\ubcda\uef4a\x08\x0c\n\r\t`1~!@#$%^&*()_+-=[]{}|;:\',./<>?', '"/\\\\\\"\\ucafe\\ubabe\\uab98\\ufcde\\ubcda\\uef4a\\b\\f\\n\\r\\t`1~!@#$%^&*()_+-=[]{}|;:\',./<>?"'),
|
||||
|
@ -37,3 +39,9 @@ class TestEncodeBaseStringAscii(TestCase):
|
|||
self.assertEquals(result, expect,
|
||||
'{0!r} != {1!r} for {2}({3!r})'.format(
|
||||
result, expect, fname, input_string))
|
||||
|
||||
def test_ordered_dict(self):
|
||||
# See issue 6105
|
||||
items = [('one', 1), ('two', 2), ('three', 3), ('four', 4), ('five', 5)]
|
||||
s = json.dumps(OrderedDict(items))
|
||||
self.assertEqual(s, '{"one": 1, "two": 2, "three": 3, "four": 4, "five": 5}')
|
||||
|
|
|
@ -63,6 +63,8 @@ Core and Builtins
|
|||
Library
|
||||
-------
|
||||
|
||||
- Issue #6105: json.dumps now respects OrderedDict's iteration order.
|
||||
|
||||
- Issue #9295: Fix a crash under Windows when calling close() on a file
|
||||
object with custom buffering from two threads at once.
|
||||
|
||||
|
|
|
@ -2071,8 +2071,9 @@ encoder_listencode_dict(PyEncoderObject *s, PyObject *rval, PyObject *dct, Py_ss
|
|||
static PyObject *empty_dict = NULL;
|
||||
PyObject *kstr = NULL;
|
||||
PyObject *ident = NULL;
|
||||
PyObject *key, *value;
|
||||
Py_ssize_t pos;
|
||||
PyObject *key = NULL;
|
||||
PyObject *value = NULL;
|
||||
PyObject *it = NULL;
|
||||
int skipkeys;
|
||||
Py_ssize_t idx;
|
||||
|
||||
|
@ -2083,7 +2084,7 @@ encoder_listencode_dict(PyEncoderObject *s, PyObject *rval, PyObject *dct, Py_ss
|
|||
if (open_dict == NULL || close_dict == NULL || empty_dict == NULL)
|
||||
return -1;
|
||||
}
|
||||
if (PyDict_Size(dct) == 0)
|
||||
if (Py_SIZE(dct) == 0)
|
||||
return PyList_Append(rval, empty_dict);
|
||||
|
||||
if (s->markers != Py_None) {
|
||||
|
@ -2117,10 +2118,12 @@ encoder_listencode_dict(PyEncoderObject *s, PyObject *rval, PyObject *dct, Py_ss
|
|||
|
||||
/* TODO: C speedup not implemented for sort_keys */
|
||||
|
||||
pos = 0;
|
||||
it = PyObject_GetIter(dct);
|
||||
if (it == NULL)
|
||||
goto bail;
|
||||
skipkeys = PyObject_IsTrue(s->skipkeys);
|
||||
idx = 0;
|
||||
while (PyDict_Next(dct, &pos, &key, &value)) {
|
||||
while ((key = PyIter_Next(it)) != NULL) {
|
||||
PyObject *encoded;
|
||||
|
||||
if (PyString_Check(key) || PyUnicode_Check(key)) {
|
||||
|
@ -2143,6 +2146,7 @@ encoder_listencode_dict(PyEncoderObject *s, PyObject *rval, PyObject *dct, Py_ss
|
|||
goto bail;
|
||||
}
|
||||
else if (skipkeys) {
|
||||
Py_DECREF(key);
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
|
@ -2156,6 +2160,10 @@ encoder_listencode_dict(PyEncoderObject *s, PyObject *rval, PyObject *dct, Py_ss
|
|||
goto bail;
|
||||
}
|
||||
|
||||
value = PyObject_GetItem(dct, key);
|
||||
if (value == NULL)
|
||||
goto bail;
|
||||
|
||||
encoded = encoder_encode_string(s, kstr);
|
||||
Py_CLEAR(kstr);
|
||||
if (encoded == NULL)
|
||||
|
@ -2170,7 +2178,13 @@ encoder_listencode_dict(PyEncoderObject *s, PyObject *rval, PyObject *dct, Py_ss
|
|||
if (encoder_listencode_obj(s, rval, value, indent_level))
|
||||
goto bail;
|
||||
idx += 1;
|
||||
Py_CLEAR(value);
|
||||
Py_DECREF(key);
|
||||
}
|
||||
if (PyErr_Occurred())
|
||||
goto bail;
|
||||
Py_CLEAR(it);
|
||||
|
||||
if (ident != NULL) {
|
||||
if (PyDict_DelItem(s->markers, ident))
|
||||
goto bail;
|
||||
|
@ -2189,6 +2203,9 @@ encoder_listencode_dict(PyEncoderObject *s, PyObject *rval, PyObject *dct, Py_ss
|
|||
return 0;
|
||||
|
||||
bail:
|
||||
Py_XDECREF(it);
|
||||
Py_XDECREF(key);
|
||||
Py_XDECREF(value);
|
||||
Py_XDECREF(kstr);
|
||||
Py_XDECREF(ident);
|
||||
return -1;
|
||||
|
|
Loading…
Reference in New Issue