Skip to content

Commit 47f2bbf

Browse files
committed
cover more cases
1 parent ef8ca4d commit 47f2bbf

File tree

2 files changed

+44
-3
lines changed

2 files changed

+44
-3
lines changed

lib/json_mend/parser.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ def parse_object_pair(object)
190190
end
191191

192192
# If we get an empty key and the next character is a closing brace, we're done.
193-
return [nil, nil, false] if key.empty? && (peek_char.nil? || peek_char == '}')
193+
return [nil, nil, false] if key.empty? && (peek_char.nil? || peek_char == '}' || @scanner.pos == pos_before_key)
194194

195195
# --- 2. Handle Duplicate Keys (Safer Method) ---
196196
# This is a critical repair for lists of objects missing a comma separator.
@@ -242,7 +242,7 @@ def parse_object_key(object)
242242
@context.pop
243243

244244
# If the key is empty, consume any stray characters to prevent infinite loops.
245-
@scanner.getch if key.empty? && !@scanner.check(/[:}]/) && !@scanner.eos?
245+
@scanner.getch if key.empty? && !@scanner.check(/[:{\[}\]]/) && !@scanner.eos?
246246

247247
[key, false, is_bracketed] # Signal that a key was parsed.
248248
end

spec/json_mend_spec.rb

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1146,7 +1146,7 @@
11461146
},
11471147
{
11481148
input: '{{{{{{',
1149-
expected_output: JSON.dump({ '' => { '' => {} } })
1149+
expected_output: JSON.dump({})
11501150
},
11511151
{
11521152
input: 'random garbage text',
@@ -1163,6 +1163,47 @@
11631163
end
11641164
end
11651165

1166+
context 'when provided deeply nested or repeated empty structures' do
1167+
[
1168+
{
1169+
input: '{{}}',
1170+
expected_output: JSON.dump({})
1171+
},
1172+
{
1173+
input: '{{{{"a": 1}}}}',
1174+
expected_output: JSON.dump({ 'a' => 1 })
1175+
},
1176+
{
1177+
input: '[[[]]]',
1178+
expected_output: JSON.dump([[[]]])
1179+
},
1180+
{
1181+
input: '{}{}{}',
1182+
# Explanation: The parser collapses consecutive top-level objects
1183+
expected_output: JSON.dump({})
1184+
},
1185+
{
1186+
input: '[{}, {}, {}]',
1187+
# Explanation: Inside an array, objects are preserved as elements
1188+
expected_output: JSON.dump([{}, {}, {}])
1189+
},
1190+
{
1191+
input: '{{ "a": 1 } { "b": 2 }}',
1192+
# Explanation: effectively parses as { "a": 1 }, then { "b": 2 }.
1193+
# Top level logic keeps the last object.
1194+
expected_output: JSON.dump({ 'b' => 2 })
1195+
},
1196+
{
1197+
input: '[[[[1]]]]',
1198+
expected_output: JSON.dump([[[[1]]]])
1199+
}
1200+
].each do |test_case|
1201+
it "repairs #{test_case[:input]} to #{test_case[:expected_output]}" do
1202+
expect(described_class.repair(test_case[:input])).to eq(test_case[:expected_output])
1203+
end
1204+
end
1205+
end
1206+
11661207
context 'with valid JSON (direct parser usage)' do
11671208
[
11681209
{

0 commit comments

Comments
 (0)