Skip to content

Commit 714ccb5

Browse files
NSHkrNSHkr
authored andcommitted
fix for invalid json per orig lib. 17 doctests, 451 tests, 0 failures, 23 excluded
1 parent bc7460e commit 714ccb5

16 files changed

+3689
-1021
lines changed

debug_position.exs

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
#!/usr/bin/env elixir
2+
3+
# Debug script to examine the specific JSON error position
4+
defmodule PositionDebugger do
5+
def run do
6+
IO.puts("=== Position-Specific JSON Debug ===\n")
7+
8+
file_path = "test/data/invalid.json"
9+
10+
case File.read(file_path) do
11+
{:ok, content} ->
12+
IO.puts("📁 Original file: #{byte_size(content)} bytes")
13+
14+
# Try our repair process step by step
15+
context = %{repairs: [], options: [], metadata: %{}}
16+
17+
# Layer 1: Content Cleaning
18+
{:ok, after_layer1, context1} = JsonRemedy.Layer1.ContentCleaning.process(content, context)
19+
IO.puts("📋 After Layer 1: #{byte_size(after_layer1)} bytes")
20+
21+
# Layer 2: Structural Repair
22+
{:ok, after_layer2, context2} = JsonRemedy.Layer2.StructuralRepair.process(after_layer1, context1)
23+
IO.puts("📋 After Layer 2: #{byte_size(after_layer2)} bytes")
24+
IO.puts("🔧 Layer 2 repairs: #{inspect(context2.repairs)}")
25+
26+
# Layer 3: Syntax Normalization
27+
{:ok, after_layer3, context3} = JsonRemedy.Layer3.SyntaxNormalization.process(after_layer2, context2)
28+
IO.puts("📋 After Layer 3: #{byte_size(after_layer3)} bytes")
29+
IO.puts("🔧 Layer 3 repairs: #{inspect(Enum.drop(context3.repairs, length(context2.repairs)))}")
30+
31+
# Now try to parse with Jason and see where it fails
32+
case Jason.decode(after_layer3) do
33+
{:ok, _} ->
34+
IO.puts("✅ JSON parses successfully!")
35+
36+
{:error, %Jason.DecodeError{position: pos} = error} ->
37+
IO.puts("❌ Jason decode error at position #{pos}")
38+
IO.puts("💡 Error: #{inspect(error)}")
39+
40+
# Show context around the error position
41+
show_context_around_position(after_layer3, pos)
42+
43+
# Also check what our original issue was around
44+
find_weiss_savage(after_layer3)
45+
end
46+
47+
{:error, reason} ->
48+
IO.puts("❌ Failed to read file: #{inspect(reason)}")
49+
end
50+
end
51+
52+
defp show_context_around_position(json_string, error_pos) do
53+
IO.puts("\n🔍 Context around error position #{error_pos}:")
54+
55+
# Show characters before and after the error position
56+
start_pos = max(0, error_pos - 100)
57+
end_pos = min(String.length(json_string), error_pos + 100)
58+
59+
context = String.slice(json_string, start_pos, end_pos - start_pos)
60+
61+
# Split into lines for better readability
62+
lines = String.split(context, "\n")
63+
64+
lines
65+
|> Enum.with_index()
66+
|> Enum.each(fn {line, idx} ->
67+
marker = if String.contains?(line, String.at(json_string, error_pos) || ""), do: " 👈", else: ""
68+
IO.puts("#{String.pad_leading(to_string(idx + 1), 3)}: #{line}#{marker}")
69+
end)
70+
71+
# Show the exact character
72+
char_at_error = String.at(json_string, error_pos)
73+
IO.puts("\n🎯 Character at position #{error_pos}: #{inspect(char_at_error)}")
74+
IO.puts("🔢 ASCII value: #{if char_at_error, do: char_at_error |> String.to_charlist() |> List.first(), else: "nil"}")
75+
end
76+
77+
defp find_weiss_savage(json_string) do
78+
IO.puts("\n🔍 Looking for 'Weiss Savage' issue:")
79+
80+
case String.contains?(json_string, "Weiss Savage") do
81+
true ->
82+
# Find all occurrences
83+
positions = find_all_positions(json_string, "Weiss Savage")
84+
IO.puts("📍 Found 'Weiss Savage' at positions: #{inspect(positions)}")
85+
86+
Enum.each(positions, fn pos ->
87+
# Show context around each occurrence
88+
start_pos = max(0, pos - 50)
89+
end_pos = min(String.length(json_string), pos + 50)
90+
context = String.slice(json_string, start_pos, end_pos - start_pos)
91+
IO.puts("📖 Context: #{context}")
92+
end)
93+
94+
false ->
95+
# Maybe it was already quoted?
96+
if String.contains?(json_string, "\"Weiss Savage\"") do
97+
IO.puts("✅ 'Weiss Savage' appears to be properly quoted")
98+
else
99+
IO.puts("❓ 'Weiss Savage' not found in repaired JSON")
100+
end
101+
end
102+
end
103+
104+
defp find_all_positions(string, substring) do
105+
find_positions(string, substring, 0, [])
106+
end
107+
108+
defp find_positions(string, substring, start, positions) do
109+
case String.contains?(String.slice(string, start..-1), substring) do
110+
true ->
111+
relative_pos = String.slice(string, start..-1) |> :binary.match(substring) |> elem(0)
112+
absolute_pos = start + relative_pos
113+
find_positions(string, substring, absolute_pos + 1, [absolute_pos | positions])
114+
115+
false ->
116+
Enum.reverse(positions)
117+
end
118+
end
119+
end
120+
121+
# Run the debugger
122+
PositionDebugger.run()

0 commit comments

Comments
 (0)