@@ -945,7 +945,7 @@ def with_timeout(seconds = 1, &)
945945 end
946946 end
947947
948- context 'edge cases' do
948+ context 'with edge cases' do
949949 [
950950 {
951951 input : '[ "key": "value", "key2": "value2" ]' ,
@@ -1049,5 +1049,129 @@ def with_timeout(seconds = 1, &)
10491049 end
10501050 end
10511051 end
1052+
1053+ context 'when provided valid complex standard json' do
1054+ [
1055+ {
1056+ input : '{"simple": "string", "number": 123, "bool": true, "nil": null}' ,
1057+ expected_output : JSON . dump ( { simple : 'string' , number : 123 , bool : true , nil : nil } )
1058+ } ,
1059+ {
1060+ input : '{"nested": {"array": [1, 2, {"deep": "obj"}]}}' ,
1061+ expected_output : JSON . dump ( { nested : { array : [ 1 , 2 , { deep : 'obj' } ] } } )
1062+ } ,
1063+ {
1064+ input : '{"unicode": "こんにちは", "emoji": "👍"}' ,
1065+ expected_output : JSON . dump ( { unicode : 'こんにちは' , emoji : '👍' } )
1066+ } ,
1067+ {
1068+ input : '{"escapes":"\" \\\\ / \\b \\f \\n \\r \\t"}' ,
1069+ expected_output : JSON . dump ( { escapes : "\" \\ / \b \f \n \r \t " } )
1070+ } ,
1071+ {
1072+ input : '{"empty_obj": {}, "empty_arr": []}' ,
1073+ expected_output : JSON . dump ( { empty_obj : { } , empty_arr : [ ] } )
1074+ }
1075+ ] . each do |test_case |
1076+ it "preserves valid json: #{ test_case [ :input ] } " do
1077+ expect ( described_class . repair ( test_case [ :input ] ) ) . to eq ( test_case [ :expected_output ] )
1078+ end
1079+ end
1080+ end
1081+
1082+ context 'when provided ambiguous number formats' do
1083+ [
1084+ {
1085+ input : '{"thousands": 1,234}' ,
1086+ expected_output : JSON . dump ( { thousands : 1.234 } )
1087+ } ,
1088+ {
1089+ input : '{"multi_comma": 1,234,567}' ,
1090+ expected_output : JSON . dump ( { multi_comma : '1,234,567' } )
1091+ } ,
1092+ {
1093+ input : '{"trailing_minus": 123-}' ,
1094+ expected_output : JSON . dump ( { trailing_minus : 123 } )
1095+ } ,
1096+ {
1097+ input : '{"underscores": 1_000}' ,
1098+ expected_output : JSON . dump ( { underscores : 1000 } )
1099+ }
1100+ ] . each do |test_case |
1101+ it "repairs number format #{ test_case [ :input ] } to #{ test_case [ :expected_output ] } " do
1102+ expect ( described_class . repair ( test_case [ :input ] ) ) . to eq ( test_case [ :expected_output ] )
1103+ end
1104+ end
1105+ end
1106+
1107+ context 'when provided tricky unicode and escapes' do
1108+ [
1109+ {
1110+ input : '{"short_unicode": "\\u12"}' ,
1111+ expected_output : JSON . dump ( { short_unicode : '\\u12' } )
1112+ } ,
1113+ {
1114+ input : '{"broken_escape": "val\\"}' ,
1115+ expected_output : JSON . dump ( { broken_escape : 'val"' } )
1116+ } ,
1117+ {
1118+ input : '{"hex_escape": "\\x41"}' ,
1119+ expected_output : JSON . dump ( { hex_escape : 'A' } )
1120+ }
1121+ ] . each do |test_case |
1122+ it "handles escapes in #{ test_case [ :input ] } " do
1123+ expect ( described_class . repair ( test_case [ :input ] ) ) . to eq ( test_case [ :expected_output ] )
1124+ end
1125+ end
1126+ end
1127+
1128+ context 'when merging dangling arrays with interference' do
1129+ [
1130+ {
1131+ input : '{"a": [1] /* comment */ [2]}' ,
1132+ expected_output : JSON . dump ( { 'a' => [ 1 , 2 ] } ) ,
1133+ desc : 'dangling array merge with intervening block comment'
1134+ } ,
1135+ {
1136+ input : "{\" a\" : [1] // comment \n [2]}" ,
1137+ expected_output : JSON . dump ( { 'a' => [ 1 , 2 ] } ) ,
1138+ desc : 'dangling array merge with intervening line comment'
1139+ } ,
1140+ {
1141+ input : '{"a": [1], "b": [3] [4]}' ,
1142+ expected_output : JSON . dump ( { 'a' => [ 1 ] , 'b' => [ 3 , 4 ] } ) ,
1143+ desc : 'dangling array on second key'
1144+ }
1145+ ] . each do |tc |
1146+ it "repairs #{ tc [ :desc ] } " do
1147+ expect ( described_class . repair ( tc [ :input ] ) ) . to eq ( tc [ :expected_output ] )
1148+ end
1149+ end
1150+ end
1151+
1152+ context 'when provided unbalanced or garbage inputs' do
1153+ [
1154+ {
1155+ input : ']]]]]]' ,
1156+ expected_output : ''
1157+ } ,
1158+ {
1159+ input : '{{{{{{' ,
1160+ expected_output : JSON . dump ( { '' => { '' => { } } } )
1161+ } ,
1162+ {
1163+ input : 'random garbage text' ,
1164+ expected_output : ''
1165+ } ,
1166+ {
1167+ input : '{"key": "value"} random garbage' ,
1168+ expected_output : JSON . dump ( { key : 'value' } )
1169+ }
1170+ ] . each do |test_case |
1171+ it "robustly handles garbage: #{ test_case [ :input ] } " do
1172+ expect ( described_class . repair ( test_case [ :input ] ) ) . to eq ( test_case [ :expected_output ] )
1173+ end
1174+ end
1175+ end
10521176 end
10531177end
0 commit comments