json-repair 0.47.7__py3-none-any.whl → 0.47.8__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -17,20 +17,31 @@ class ObjectComparer: # pragma: no cover
17
17
  return False
18
18
 
19
19
  if isinstance(obj1, dict):
20
- # Quick length check before key compares
21
- if len(obj1) != len(obj2):
20
+ # Check that both are dicts and same length
21
+ if not isinstance(obj2, dict) or len(obj1) != len(obj2):
22
22
  return False
23
23
  for key in obj1:
24
24
  if key not in obj2:
25
25
  return False
26
+ # Recursively compare each value
26
27
  if not ObjectComparer.is_same_object(obj1[key], obj2[key]):
27
28
  return False
28
29
  return True
29
30
 
30
31
  elif isinstance(obj1, list):
31
- if len(obj1) != len(obj2):
32
+ # Check that both are lists and same length
33
+ if not isinstance(obj2, list) or len(obj1) != len(obj2):
32
34
  return False
35
+ # Recursively compare each item
33
36
  return all(ObjectComparer.is_same_object(obj1[i], obj2[i]) for i in range(len(obj1)))
34
37
 
35
- # For atoms: types already match, so just return True
38
+ # For atomic values: types already match, so return True
36
39
  return True
40
+
41
+ @staticmethod
42
+ def is_strictly_empty(value: Any) -> bool:
43
+ """
44
+ Returns True if value is an empty container (str, list, dict, set, tuple).
45
+ Returns False for non-containers like None, 0, False, etc.
46
+ """
47
+ return isinstance(value, str | list | dict | set | tuple) and len(value) == 0
@@ -2,6 +2,7 @@ from typing import TYPE_CHECKING
2
2
 
3
3
  from .constants import STRING_DELIMITERS, JSONReturnType
4
4
  from .json_context import ContextValues
5
+ from .object_comparer import ObjectComparer
5
6
 
6
7
  if TYPE_CHECKING:
7
8
  from .json_parser import JSONParser
@@ -28,7 +29,7 @@ def parse_array(self: "JSONParser") -> list[JSONReturnType]:
28
29
  value = self.parse_json()
29
30
 
30
31
  # It is possible that parse_json() returns nothing valid, so we increase by 1
31
- if value == "":
32
+ if ObjectComparer.is_strictly_empty(value):
32
33
  self.index += 1
33
34
  elif value == "..." and self.get_char_at(-1) == ".":
34
35
  self.log(
@@ -64,17 +64,12 @@ def parse_object(self: "JSONParser") -> dict[str, JSONReturnType]:
64
64
  # If the string is empty but there is a object divider, we are done here
65
65
  break
66
66
  if ContextValues.ARRAY in self.context.context and key in obj:
67
- if self.stream_stable:
68
- # This is possibly another problem, the key is incomplete and it "appears" duplicate
69
- # Let's just do nothing
70
- pass
71
- else:
72
- self.log(
73
- "While parsing an object we found a duplicate key, closing the object here and rolling back the index",
74
- )
75
- self.index = rollback_index - 1
76
- # add an opening curly brace to make this work
77
- self.json_str = self.json_str[: self.index + 1] + "{" + self.json_str[self.index + 1 :]
67
+ self.log(
68
+ "While parsing an object we found a duplicate key, closing the object here and rolling back the index",
69
+ )
70
+ self.index = rollback_index - 1
71
+ # add an opening curly brace to make this work
72
+ self.json_str = self.json_str[: self.index + 1] + "{" + self.json_str[self.index + 1 :]
78
73
  break
79
74
 
80
75
  # Skip filler whitespaces
@@ -324,10 +324,18 @@ def parse_string(self: "JSONParser") -> str | bool | None:
324
324
  i += 1
325
325
  i = self.skip_to_character(character=rstring_delimiter, idx=i)
326
326
  next_c = self.get_char_at(i)
327
- # Ok now I found a delimiter, let's skip whitespaces and see if next we find a }
327
+ # Ok now I found a delimiter, let's skip whitespaces and see if next we find a } or a ,
328
328
  i += 1
329
329
  i = self.skip_whitespaces_at(idx=i, move_main_index=False)
330
330
  next_c = self.get_char_at(i)
331
+ if next_c in ["}", ","]:
332
+ self.log(
333
+ "While parsing a string, we a misplaced quote that would have closed the string but has a different meaning here, ignoring it",
334
+ )
335
+ string_acc += str(char)
336
+ self.index += 1
337
+ char = self.get_char_at()
338
+ continue
331
339
  elif next_c == rstring_delimiter and self.get_char_at(i - 1) != "\\":
332
340
  # Check if self.index:self.index+i is only whitespaces, break if that's the case
333
341
  if all(str(self.get_char_at(j)).isspace() for j in range(1, i) if self.get_char_at(j)):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: json_repair
3
- Version: 0.47.7
3
+ Version: 0.47.8
4
4
  Summary: A package to repair broken json strings
5
5
  Author-email: Stefano Baccianella <4247706+mangiucugna@users.noreply.github.com>
6
6
  License: MIT License
@@ -4,18 +4,18 @@ json_repair/constants.py,sha256=cv2gvyosuq0me0600WyTysM9avrtfXPuXYR26tawcuo,158
4
4
  json_repair/json_context.py,sha256=WsMOjqpGSr6aaDONcrk8UFtTurzWon2Qq9AoBBYseoI,934
5
5
  json_repair/json_parser.py,sha256=rTuL8ESslQ4XK9fkLmBIpS4e8xr6QwlZRVyJwzJFqBE,7356
6
6
  json_repair/json_repair.py,sha256=txblCJtcTpXcQaT15tavulkJPtyRYe2cfYpPHZcvPv0,11233
7
- json_repair/object_comparer.py,sha256=LlIF0MisRglzC-CiG5AxAEDCBWBHeJd-6uXYx0uRmCk,1175
8
- json_repair/parse_array.py,sha256=aNFJUsa_i1_wjwLKSMFfU36ArKOI5OxFG_TJW9sLGDw,2109
7
+ json_repair/object_comparer.py,sha256=XKV3MRab8H7_v4sm-wpEa5le0XX9OeycWo5S-MFm-GI,1716
8
+ json_repair/parse_array.py,sha256=-rh65JcfT-FtXiR6s8RYlMfI-6LzVr08ytlDh6Z2CFE,2181
9
9
  json_repair/parse_boolean_or_null.py,sha256=WMSkvvxsp4wvauBcDqtt9WnLMD5SMoxeRfZFXp3FEBc,890
10
10
  json_repair/parse_comment.py,sha256=JHtQ_QlxOvPNnMh7lhUaoTjFGelqjhTNq7qn9xUE7SU,2648
11
11
  json_repair/parse_number.py,sha256=33zAtkbuVzi9Lqjxu7cXn9WlVzd3WjRx9Ln_LFzVL4o,1259
12
- json_repair/parse_object.py,sha256=vPxSTnPW74v8nRI_2ASt8dO4a5DWzbEt4c-zb3oFM_o,4802
13
- json_repair/parse_string.py,sha256=GItlhNwDGRWUxgEvZhYdwLYu5bgHiIiliH64vDzIrj4,22238
12
+ json_repair/parse_object.py,sha256=UzkY0C5NSE2CtVnZwugMyhhtUJPgs0MwBb4kF4l2ftU,4563
13
+ json_repair/parse_string.py,sha256=QTMHdc9_tLwzFwYMVrSJbkWoeV6-mQK7e2RDbJR_JJM,22677
14
14
  json_repair/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
15
  json_repair/string_file_wrapper.py,sha256=tGkWBEUPE-CZPf4uSM5NE9oSDTpskX0myJiXsl-gbds,4333
16
- json_repair-0.47.7.dist-info/licenses/LICENSE,sha256=wrjQo8MhNrNCicXtMe3MHmS-fx8AmQk1ue8AQwiiFV8,1076
17
- json_repair-0.47.7.dist-info/METADATA,sha256=Xr4XqdXIa0XWur-wt7d0rK4s7N5D2VPWJ2B_h0oHRKM,12411
18
- json_repair-0.47.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
19
- json_repair-0.47.7.dist-info/entry_points.txt,sha256=SNfge3zPSP-ASqriYU9r3NAPaXdseYr7ciPMKdV2uSw,57
20
- json_repair-0.47.7.dist-info/top_level.txt,sha256=7-VZwZN2CgB_n0NlSLk-rEUFh8ug21lESbsblOYuZqw,12
21
- json_repair-0.47.7.dist-info/RECORD,,
16
+ json_repair-0.47.8.dist-info/licenses/LICENSE,sha256=wrjQo8MhNrNCicXtMe3MHmS-fx8AmQk1ue8AQwiiFV8,1076
17
+ json_repair-0.47.8.dist-info/METADATA,sha256=S63nu7L4zgNPB3HzlA4uaJtb3204R_b1pCAUrShwyjU,12411
18
+ json_repair-0.47.8.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
19
+ json_repair-0.47.8.dist-info/entry_points.txt,sha256=SNfge3zPSP-ASqriYU9r3NAPaXdseYr7ciPMKdV2uSw,57
20
+ json_repair-0.47.8.dist-info/top_level.txt,sha256=7-VZwZN2CgB_n0NlSLk-rEUFh8ug21lESbsblOYuZqw,12
21
+ json_repair-0.47.8.dist-info/RECORD,,