Merge pull request #32 from alexwlchan/name-value-pairs
- ID
d991f3a- date
2025-05-04 14:45:16+00:00- author
Alex Chan <alex@alexwlchan.net>- parents
5ab6b53,45fd4be- message
Merge pull request #32 from alexwlchan/name-value-pairs 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" }'
)