11import json
2- from typing import List , Tuple , Set , Dict
2+ from typing import Dict , List , Set , Tuple
33
44JsonPrimitive = str | int | float | bool | None
55type JsonValue = JsonPrimitive | JsonObject | JsonArray
66JsonPair = tuple [str , JsonValue ]
77JsonObject = list [JsonPair ]
88JsonArray = list [JsonValue ]
99
10+
1011class DuplicateKeyChecker :
1112 """JSON structure duplicate key detector.
12-
13+
1314 Tracks duplicate keys by maintaining path context during traversal.
1415 Paths are recorded in dot notation with array indices:
1516 - Objects: parent.child
@@ -25,7 +26,7 @@ def __init__(self):
2526 self .current_duplicate_index : Dict [str , int ] = {}
2627
2728 def get_path_with_index (self , path : List [str ], key : str ) -> List [str ]:
28- current_level = '.' .join (path )
29+ current_level = "." .join (path )
2930 index_map = self .current_duplicate_index .setdefault (current_level , {})
3031 count = index_map .get (key , 0 )
3132 index_map [key ] = count + 1
@@ -39,20 +40,22 @@ def get_path_with_index(self, path: List[str], key: str) -> List[str]:
3940
4041 def check_key (self , key : str , path : List [str ]) -> None :
4142 """Check if a key at the current path is a duplicate.
42-
43+
4344 A duplicate occurs when the same key appears twice at the same
4445 nesting level, even if the values differ.
4546 """
46- current_level = '.' .join (path )
47+ current_level = "." .join (path )
4748 current_keys = self .key_registry .setdefault (current_level , {})
4849 if key in current_keys :
4950 self .duplicate_keys .add (key )
50- self .duplicate_paths .add ('.' .join (path + [key ]))
51+ self .duplicate_paths .add ("." .join (path + [key ]))
5152 print (f"Found duplicate key: { key } at path: { '.' .join (path + [key ])} " )
5253 else :
5354 current_keys [key ] = True
5455
55- def process_collection (self , value : JsonObject | JsonArray , path : list [str ], key : str ) -> None :
56+ def process_collection (
57+ self , value : JsonObject | JsonArray , path : list [str ], key : str
58+ ) -> None :
5659 """Determine if the given 'value' is an object or an array and handle it."""
5760 new_path = self .get_path_with_index (path , key )
5861 if value and isinstance (value [0 ], tuple ):
@@ -78,13 +81,14 @@ def traverse_array(self, items: JsonArray, path: list[str]) -> None:
7881 continue
7982 self .process_collection (item , base_path , f"{ array_path } [{ idx } ]" )
8083
84+
8185def check_duplicate_keys (json_content : str ) -> Tuple [List [str ], List [str ]]:
8286 """Find all duplicate keys in a JSON string.
83-
87+
8488 Traverses the entire JSON structure and reports:
8589 - List of keys that appear multiple times at the same level
8690 - Full paths to each duplicate key occurrence
87-
91+
8892 A key is considered duplicate if it appears multiple times within
8993 the same object, regardless of nesting level or array position.
9094 """
@@ -93,10 +97,10 @@ def check_duplicate_keys(json_content: str) -> Tuple[List[str], List[str]]:
9397 print ("Parsed JSON:" , parsed_data )
9498 except json .JSONDecodeError :
9599 raise ValueError ("Error: Invalid JSON format" )
96-
100+
97101 checker = DuplicateKeyChecker ()
98- checker .traverse_json (parsed_data , [' root' ])
99-
102+ checker .traverse_json (parsed_data , [" root" ])
103+
100104 duplicates = list (checker .duplicate_keys )
101105 paths = list (checker .duplicate_paths )
102106 print ("Final duplicates:" , duplicates )
0 commit comments