ogx786 commited on
Commit
d4d9b1f
·
verified ·
1 Parent(s): 8ae38d8

Update data_extraction.py

Browse files
Files changed (1) hide show
  1. data_extraction.py +68 -11
data_extraction.py CHANGED
@@ -43,33 +43,90 @@ INSTRUCTIONS = {
43
  # --------------------------------------------------------------------------
44
  # Loading
45
  # --------------------------------------------------------------------------
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
  def load_records(filepaths):
47
  """
48
- Handles three shapes:
49
  1) {"response": [ {...}, {...}, ... ]} (paginated API wrapper)
50
  2) [ {...}, {...}, ... ] (plain list of records)
51
  3) JSON Lines: one record dict per line
52
- Returns a flat list of record dicts.
 
 
53
  """
54
  records = []
55
  for fp in filepaths:
56
- with open(fp, "r", encoding="utf-8") as fh:
57
  raw = fh.read().strip()
 
 
 
 
 
58
  try:
59
  obj = json.loads(raw)
60
- if isinstance(obj, dict) and "response" in obj:
61
- records.extend(obj["response"])
62
- elif isinstance(obj, list):
63
- records.extend(obj)
64
- elif isinstance(obj, dict):
65
- records.append(obj)
 
 
 
 
 
 
66
  except json.JSONDecodeError:
67
- # fall back to JSON Lines
 
 
 
68
  for line in raw.splitlines():
69
  line = line.strip()
70
  if not line:
71
  continue
72
- records.append(json.loads(line))
 
 
 
 
 
 
 
 
 
73
  return records
74
 
75
 
 
43
  # --------------------------------------------------------------------------
44
  # Loading
45
  # --------------------------------------------------------------------------
46
+ def _absorb(obj, records):
47
+ """Given a parsed JSON value, pull out record dicts from known shapes."""
48
+ if isinstance(obj, dict) and "response" in obj:
49
+ records.extend(obj["response"])
50
+ elif isinstance(obj, list):
51
+ records.extend(obj)
52
+ elif isinstance(obj, dict):
53
+ records.append(obj)
54
+
55
+
56
+ def _parse_concatenated_json(raw):
57
+ """
58
+ Parses a string containing one or more back-to-back JSON values
59
+ (e.g. multiple {"response": [...]} wrapper objects with no separator,
60
+ or no enclosing list) using a streaming decoder.
61
+ Returns a list of parsed top-level JSON values.
62
+ """
63
+ decoder = json.JSONDecoder()
64
+ values = []
65
+ idx = 0
66
+ n = len(raw)
67
+ while idx < n:
68
+ while idx < n and raw[idx].isspace():
69
+ idx += 1
70
+ if idx >= n:
71
+ break
72
+ obj, end = decoder.raw_decode(raw, idx)
73
+ values.append(obj)
74
+ idx = end
75
+ return values
76
+
77
+
78
  def load_records(filepaths):
79
  """
80
+ Handles several shapes robustly:
81
  1) {"response": [ {...}, {...}, ... ]} (paginated API wrapper)
82
  2) [ {...}, {...}, ... ] (plain list of records)
83
  3) JSON Lines: one record dict per line
84
+ 4) Multiple JSON values concatenated back-to-back in one file
85
+ Also strips BOM and skips empty files, reporting problems per-file
86
+ instead of crashing the whole run.
87
  """
88
  records = []
89
  for fp in filepaths:
90
+ with open(fp, "r", encoding="utf-8-sig") as fh: # utf-8-sig strips BOM if present
91
  raw = fh.read().strip()
92
+
93
+ if not raw:
94
+ print(f" [skip] {fp} is empty")
95
+ continue
96
+
97
  try:
98
  obj = json.loads(raw)
99
+ _absorb(obj, records)
100
+ continue
101
+ except json.JSONDecodeError:
102
+ pass
103
+
104
+ try:
105
+ values = _parse_concatenated_json(raw)
106
+ if values:
107
+ for v in values:
108
+ _absorb(v, records)
109
+ print(f" [ok] {fp}: parsed as {len(values)} concatenated JSON value(s)")
110
+ continue
111
  except json.JSONDecodeError:
112
+ pass
113
+
114
+ try:
115
+ line_records = []
116
  for line in raw.splitlines():
117
  line = line.strip()
118
  if not line:
119
  continue
120
+ line_records.append(json.loads(line))
121
+ for v in line_records:
122
+ _absorb(v, records)
123
+ print(f" [ok] {fp}: parsed as JSON Lines ({len(line_records)} lines)")
124
+ continue
125
+ except json.JSONDecodeError as e:
126
+ print(f" [FAILED] {fp}: could not parse as JSON, concatenated JSON, or JSON Lines.")
127
+ print(f" First 200 chars: {raw[:200]!r}")
128
+ print(f" Error: {e}")
129
+
130
  return records
131
 
132