]> granicus.if.org Git - python/commitdiff
Backport r72961 fixing issue #6105: json.dumps not following OrderedDict iteration...
authorRaymond Hettinger <python@rcn.com>
Sat, 30 Oct 2010 07:29:44 +0000 (07:29 +0000)
committerRaymond Hettinger <python@rcn.com>
Sat, 30 Oct 2010 07:29:44 +0000 (07:29 +0000)
Lib/json/tests/test_encode_basestring_ascii.py
Misc/NEWS
Modules/_json.c

index 62abe5bf07671ff3d97aa90ee934e04442156b84..02889f084bb2e477636a24935cf578ecad11524f 100644 (file)
@@ -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}')
index 665271ec761a334019ad42d4395a4900ea14475c..eeff4a77607a10ff3b8affcd12d9ef7234994bf1 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -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.
 
index d81721a00aa54bee339b128da5629d03b47218d1..de7e1711e6b5ae91deead461acf03588a9160f20 100644 (file)
@@ -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;