Skip to main content

Tweak the naming to match how JSON is usually described

ID
45fd4be
date
2025-05-04 14:00:06+00:00
author
Alex Chan <alex@alexwlchan.net>
parent
5ab6b53
message
Tweak the naming to match how JSON is usually described
changed files
4 files, 25 additions, 19 deletions

Changed files

CHANGELOG.md (3790) → CHANGELOG.md (3923)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index b9a9cc0..a9a80c0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,9 @@
 # CHANGELOG
 
+## v1.2.3 - 2025-05-04
+
+Tweak the error message introduced in v1.2.2 -- JSON objects are **name**/value pairs, not key/value pairs.
+
 ## v1.2.2 - 2025-05-03
 
 Duplicate keys in JSON objects are now rejected as an error.

src/javascript_data_files/__init__.py (6783) → src/javascript_data_files/__init__.py (6783)

diff --git a/src/javascript_data_files/__init__.py b/src/javascript_data_files/__init__.py
index 6e0d030..2f72ea2 100644
--- a/src/javascript_data_files/__init__.py
+++ b/src/javascript_data_files/__init__.py
@@ -22,7 +22,7 @@ from .decoder import decode_from_js
 from .encoder import encode_as_js, encode_as_json
 
 
-__version__ = "1.2.2"
+__version__ = "1.2.3"
 __all__ = [
     "read_js",
     "read_typed_js",

src/javascript_data_files/decoder.py (2194) → src/javascript_data_files/decoder.py (2197)

diff --git a/src/javascript_data_files/decoder.py b/src/javascript_data_files/decoder.py
index 70440a9..be5efdf 100644
--- a/src/javascript_data_files/decoder.py
+++ b/src/javascript_data_files/decoder.py
@@ -28,13 +28,15 @@ def decode_from_js(js_string: str, *, varname: str) -> typing.Any:
     return decode_from_json(json_string)
 
 
-def _parse_object_pairs(pairs: list[tuple[str, typing.Any]]) -> dict[str, typing.Any]:
+def dict_with_unique_names(
+    pairs: list[tuple[str, typing.Any]],
+) -> dict[str, typing.Any]:
     """
-    Convert any object literal into a dict.  This receives a list of
-    key-value pairs and returns a dict.
+    Convert a list of name/value pairs to a dict, but only if the
+    names are unique.
 
     This is similar to the builtin parser, but it will look for
-    duplicate keys and throw a ValueError if they're found; this is
+    duplicate names and throw a ValueError if they're found; this is
     a protection against me making a copy/paste error in my JavaScript.
     """
     # First try to parse the object as a dictionary; if it's the same
@@ -45,20 +47,20 @@ def _parse_object_pairs(pairs: list[tuple[str, typing.Any]]) -> dict[str, typing
     if len(pairs_as_dict) == len(pairs):
         return pairs_as_dict
 
-    # Otherwise, let's work out what the duplicate key(s) were, so we
+    # Otherwise, let's work out what the duplicate name(s) were, so we
     # can throw an appropriate error message for the user.
     import collections
 
-    key_tally = collections.Counter(k for k, _ in pairs)
+    name_tally = collections.Counter(k for k, _ in pairs)
 
-    duplicate_keys = [k for k, count in key_tally.items() if count > 1]
-    assert len(duplicate_keys) > 0
+    duplicate_names = [k for k, count in name_tally.items() if count > 1]
+    assert len(duplicate_names) > 0
 
-    if len(duplicate_keys) == 1:
-        raise ValueError(f"Found duplicate key in JSON object: {duplicate_keys[0]}")
+    if len(duplicate_names) == 1:
+        raise ValueError(f"Found duplicate name in JSON object: {duplicate_names[0]}")
     else:
         raise ValueError(
-            f"Found duplicate keys in JSON object: {', '.join(duplicate_keys)}"
+            f"Found duplicate names in JSON object: {', '.join(duplicate_names)}"
         )
 
 
@@ -66,4 +68,4 @@ def decode_from_json(json_string: str) -> typing.Any:
     """
     Parse a string as a JSON value.
     """
-    return json.loads(json_string, object_pairs_hook=_parse_object_pairs)
+    return json.loads(json_string, object_pairs_hook=dict_with_unique_names)

tests/test_decoder.py (1063) → tests/test_decoder.py (1069)

diff --git a/tests/test_decoder.py b/tests/test_decoder.py
index 5676fb8..ad79f74 100644
--- a/tests/test_decoder.py
+++ b/tests/test_decoder.py
@@ -15,21 +15,21 @@ from javascript_data_files.decoder import decode_from_json
         '[{ "nested": { "sides": 3, "sides": 4 } }]',
     ],
 )
-def test_object_with_duplicate_keys_is_rejected(json_string: str) -> None:
+def test_object_with_duplicate_names_is_rejected(json_string: str) -> None:
     """
     Trying to decode a JavaScript string which includes an object
-    with duplicate keys throws a ValueError.
+    with duplicate names throws a ValueError.
     """
-    with pytest.raises(ValueError, match="Found duplicate key in JSON object: sides"):
+    with pytest.raises(ValueError, match="Found duplicate name in JSON object: sides"):
         decode_from_json(json_string)
 
 
-def test_object_with_multiple_duplicate_keys_is_rejected() -> None:
+def test_object_with_multiple_duplicate_names_is_rejected() -> None:
     """
     Trying to decode a JavaScript string which includes an object
-    with multiple duplicate keys throws a ValueError.
+    with multiple duplicate names throws a ValueError.
     """
-    with pytest.raises(ValueError, match="Found duplicate keys in JSON object:"):
+    with pytest.raises(ValueError, match="Found duplicate names in JSON object:"):
         decode_from_json(
             '{ "sides": 3, "colour": "blue", "sides": 4, "colour": "red" }'
         )