diff --git a/pre_commit_hooks/check_json.py b/pre_commit_hooks/check_json.py index 6026270c..db589d01 100644 --- a/pre_commit_hooks/check_json.py +++ b/pre_commit_hooks/check_json.py @@ -1,7 +1,23 @@ import argparse import json +from typing import Any +from typing import Dict +from typing import List from typing import Optional from typing import Sequence +from typing import Tuple + + +def raise_duplicate_keys( + ordered_pairs: List[Tuple[str, Any]], +) -> Dict[str, Any]: + d = {} + for key, val in ordered_pairs: + if key in d: + raise ValueError(f'Duplicate key: {key}') + else: + d[key] = val + return d def main(argv: Optional[Sequence[str]] = None) -> int: @@ -13,7 +29,7 @@ def main(argv: Optional[Sequence[str]] = None) -> int: for filename in args.filenames: with open(filename, 'rb') as f: try: - json.load(f) + json.load(f, object_pairs_hook=raise_duplicate_keys) except ValueError as exc: print(f'{filename}: Failed to json decode ({exc})') retval = 1 diff --git a/testing/resources/duplicate_key_json.json b/testing/resources/duplicate_key_json.json new file mode 100644 index 00000000..8a432623 --- /dev/null +++ b/testing/resources/duplicate_key_json.json @@ -0,0 +1,4 @@ +{ + "hello": "world", + "hello": "planet" +} diff --git a/tests/check_json_test.py b/tests/check_json_test.py index c63dc4c8..e010faaa 100644 --- a/tests/check_json_test.py +++ b/tests/check_json_test.py @@ -9,6 +9,7 @@ ('bad_json.notjson', 1), ('bad_json_latin1.nonjson', 1), ('ok_json.json', 0), + ('duplicate_key_json.json', 1), ), ) def test_main(capsys, filename, expected_retval):