]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-100272: Fix JSON serialization of OrderedDict (GH-100273)
authorSerhiy Storchaka <storchaka@gmail.com>
Sat, 17 Dec 2022 12:32:48 +0000 (14:32 +0200)
committerGitHub <noreply@github.com>
Sat, 17 Dec 2022 12:32:48 +0000 (14:32 +0200)
It now preserves the order of keys.

Lib/test/test_json/test_default.py
Misc/NEWS.d/next/Library/2022-12-15-18-28-13.gh-issue-100272.D1O9Ey.rst [new file with mode: 0644]
Modules/_json.c

index 9b8325e9c3816b6bfc7fb042fd64ca277bfb3cdf..3ce16684a08272df566ae62081c65888d91cd309 100644 (file)
@@ -1,3 +1,4 @@
+import collections
 from test.test_json import PyTest, CTest
 
 
@@ -7,6 +8,16 @@ class TestDefault:
             self.dumps(type, default=repr),
             self.dumps(repr(type)))
 
+    def test_ordereddict(self):
+        od = collections.OrderedDict(a=1, b=2, c=3, d=4)
+        od.move_to_end('b')
+        self.assertEqual(
+            self.dumps(od),
+            '{"a": 1, "c": 3, "d": 4, "b": 2}')
+        self.assertEqual(
+            self.dumps(od, sort_keys=True),
+            '{"a": 1, "b": 2, "c": 3, "d": 4}')
+
 
 class TestPyDefault(TestDefault, PyTest): pass
 class TestCDefault(TestDefault, CTest): pass
diff --git a/Misc/NEWS.d/next/Library/2022-12-15-18-28-13.gh-issue-100272.D1O9Ey.rst b/Misc/NEWS.d/next/Library/2022-12-15-18-28-13.gh-issue-100272.D1O9Ey.rst
new file mode 100644 (file)
index 0000000..2fb0892
--- /dev/null
@@ -0,0 +1 @@
+Fix JSON serialization of OrderedDict.  It now preserves the order of keys.
index 429b4ee0fa8d8ded6f9c8b1cfe77e95a3680f970..6879ad3d0722b6cb08c4d2c78169d235fe1ba6fa 100644 (file)
@@ -1570,10 +1570,9 @@ encoder_listencode_dict(PyEncoderObject *s, _PyUnicodeWriter *writer,
         */
     }
 
-    if (s->sort_keys) {
-
-        items = PyDict_Items(dct);
-        if (items == NULL || PyList_Sort(items) < 0)
+    if (s->sort_keys || !PyDict_CheckExact(dct)) {
+        items = PyMapping_Items(dct);
+        if (items == NULL || (s->sort_keys && PyList_Sort(items) < 0))
             goto bail;
 
         for (Py_ssize_t  i = 0; i < PyList_GET_SIZE(items); i++) {