Skip to content

Commit e18ffdb

Browse files
committed
fix: proper JSON and CSV escaping for filenames in metrics output
- Added escapeJson() method to handle quotes, backslashes, and control characters - Added escapeCsv() method to handle commas, quotes, and newlines - Fixed malformed string literals in escape sequences - Prevents broken output when filenames contain special characters - Ensures downstream parsing of JSON/CSV metrics works correctly The escaping properly handles: - JSON: quotes, backslashes, control characters, Unicode - CSV: commas, quotes, newlines (wraps in quotes when needed)
1 parent 2b5bdfe commit e18ffdb

File tree

1 file changed

+84
-2
lines changed

1 file changed

+84
-2
lines changed

json-java21-schema/src/test/java/io/github/simbo1905/json/schema/JsonSchemaCheckIT.java

Lines changed: 84 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ private static String buildJsonSummary(boolean strict, String timestamp) {
203203
if (!first) totals.append(",\n");
204204
first = false;
205205
totals.append(" {\n");
206-
totals.append(" \"file\": \"").append(file).append("\",\n");
206+
totals.append(" \"file\": ").append(escapeJson(file)).append(",\n");
207207
totals.append(" \"groups\": ").append(counters.groups.sum()).append(",\n");
208208
totals.append(" \"tests\": ").append(counters.tests.sum()).append(",\n");
209209
totals.append(" \"run\": ").append(counters.run.sum()).append(",\n");
@@ -240,7 +240,7 @@ private static String buildCsvSummary(boolean strict, String timestamp) {
240240
java.util.Collections.sort(files);
241241
for (String file : files) {
242242
var counters = METRICS.perFile.get(file);
243-
csv.append(file).append(",");
243+
csv.append(escapeCsv(file)).append(",");
244244
csv.append(counters.groups.sum()).append(",");
245245
csv.append(counters.tests.sum()).append(",");
246246
csv.append(counters.run.sum()).append(",");
@@ -252,6 +252,88 @@ private static String buildCsvSummary(boolean strict, String timestamp) {
252252
}
253253
return csv.toString();
254254
}
255+
256+
/**
257+
* Escapes a string for safe inclusion in JSON output.
258+
* Handles quotes, backslashes, and control characters.
259+
*/
260+
private static String escapeJson(String input) {
261+
if (input == null) {
262+
return "null";
263+
}
264+
265+
StringBuilder result = new StringBuilder();
266+
result.append('"');
267+
268+
for (int i = 0; i < input.length(); i++) {
269+
char ch = input.charAt(i);
270+
switch (ch) {
271+
case '"':
272+
result.append("\\\"");
273+
break;
274+
case '\\':
275+
result.append("\\\\");
276+
break;
277+
case '\b':
278+
result.append("\\b");
279+
break;
280+
case '\f':
281+
result.append("\\f");
282+
break;
283+
case '\n':
284+
result.append("\\n");
285+
break;
286+
case '\r':
287+
result.append("\\r");
288+
break;
289+
case '\t':
290+
result.append("\\t");
291+
break;
292+
default:
293+
if (ch < 0x20 || ch > 0x7e) {
294+
// Unicode escape for control characters and non-ASCII
295+
result.append("\\u").append(String.format("%04x", (int) ch));
296+
} else {
297+
result.append(ch);
298+
}
299+
}
300+
}
301+
302+
result.append('"');
303+
return result.toString();
304+
}
305+
306+
/**
307+
* Escapes a string for safe inclusion in CSV output.
308+
* Handles commas, quotes, and newlines by wrapping in quotes if needed.
309+
*/
310+
private static String escapeCsv(String input) {
311+
if (input == null) {
312+
return "";
313+
}
314+
315+
// Check if escaping is needed
316+
boolean needsEscaping = input.contains(",") || input.contains("\"") ||
317+
input.contains("\n") || input.contains("\r");
318+
319+
if (!needsEscaping) {
320+
return input;
321+
}
322+
323+
// Wrap in quotes and escape internal quotes
324+
StringBuilder result = new StringBuilder();
325+
result.append('"');
326+
for (int i = 0; i < input.length(); i++) {
327+
char ch = input.charAt(i);
328+
if (ch == '"') {
329+
result.append("\"\""); // Double quotes to escape
330+
} else {
331+
result.append(ch);
332+
}
333+
}
334+
result.append('"');
335+
return result.toString();
336+
}
255337
}
256338

257339
/**

0 commit comments

Comments
 (0)