diff --git a/src/json.c b/src/json.c index 689f6ac510e..c1daba199c3 100644 --- a/src/json.c +++ b/src/json.c @@ -352,7 +352,12 @@ lisp_to_json_toplevel_1 (Lisp_Object lisp, json_t **json) /* We can't specify the length, so the string must be null-terminated. */ check_string_without_embedded_nulls (key); - int status = json_object_set_new (*json, SSDATA (key), + const char *key_str = SSDATA (key); + /* Reject duplicate keys. These are possible if the hash + table test is not `equal'. */ + if (json_object_get (*json, key_str) != NULL) + wrong_type_argument (Qjson_value_p, lisp); + int status = json_object_set_new (*json, key_str, lisp_to_json (HASH_VALUE (h, i))); if (status == -1) /* FIXME: A failure here might also indicate that the diff --git a/test/src/json-tests.el b/test/src/json-tests.el index 9884e9a2d57..5d9f6b3840c 100644 --- a/test/src/json-tests.el +++ b/test/src/json-tests.el @@ -52,6 +52,14 @@ (should (equal (json-serialize table) "{\"abc\":[1,2,true],\"def\":null}")))) +(ert-deftest json-serialize/object-with-duplicate-keys () + (skip-unless (fboundp 'json-serialize)) + (let ((table (make-hash-table :test #'eq))) + (puthash (copy-sequence "abc") [1 2 t] table) + (puthash (copy-sequence "abc") :null table) + (should (equal (hash-table-count table) 2)) + (should-error (json-serialize table) :type 'wrong-type-argument))) + (ert-deftest json-parse-string/object () (skip-unless (fboundp 'json-parse-string)) (let ((input