From 0aa5bb6a099fd7bcfefcf7eeffa48f6a133dca08 Mon Sep 17 00:00:00 2001 From: dnetmj Date: Tue, 4 Aug 2015 15:59:11 -0400 Subject: [PATCH] Fix parsing of quoted strings Pretty printing was not distinguishing between single-quote delimited strings and double-quote delimited strings, which in earlier revisions caused an exception which the latest revision caught and swallowed, but didn't really fix. This change refactors the prettyPrint method as a state machine which correctly handles both quoting and escaping within strings. The isEscaped method is eliminated. --- .../jsonpath/internal/JsonFormatter.java | 133 ++++++++++-------- 1 file changed, 76 insertions(+), 57 deletions(-) diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/JsonFormatter.java b/json-path/src/main/java/com/jayway/jsonpath/internal/JsonFormatter.java index e07b2811..34dd779e 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/internal/JsonFormatter.java +++ b/json-path/src/main/java/com/jayway/jsonpath/internal/JsonFormatter.java @@ -25,78 +25,97 @@ public class JsonFormatter { private static final String NEW_LINE = System.getProperty("line.separator"); + private static final int MODE_SINGLE = 100; + private static final int MODE_DOUBLE = 101; + private static final int MODE_ESCAPE_SINGLE = 102; + private static final int MODE_ESCAPE_DOUBLE = 103; + private static final int MODE_BETWEEN = 104; + private static void appendIndent(StringBuilder sb, int count) { for (; count > 0; --count) sb.append(INDENT); } - private static boolean isEscaped(StringBuilder sb, int index) { - boolean escaped = false; - int idx = Math.min(index, sb.length()); - try { - while (idx > 0 && sb.charAt(--idx) == '\\') { - escaped = !escaped; - } - } catch (Exception e){ - logger.warn("Failed to check escaped ", e); - } - return escaped; - } - public static String prettyPrint(String input) { input = input.replaceAll("[\\r\\n]", ""); StringBuilder output = new StringBuilder(input.length() * 2); - boolean quoteOpened = false; + int mode = MODE_BETWEEN; int depth = 0; for (int i = 0; i < input.length(); ++i) { char ch = input.charAt(i); - switch (ch) { - case '{': - case '[': - output.append(ch); - if (!quoteOpened) { - output.append(NEW_LINE); - appendIndent(output, ++depth); - } - break; - case '}': - case ']': - if (quoteOpened) - output.append(ch); - else { - output.append(NEW_LINE); - appendIndent(output, --depth); - output.append(ch); - } - break; - case '"': - case '\'': - output.append(ch); - if (quoteOpened) { - if (!isEscaped(output, i)) - quoteOpened = false; - } else quoteOpened = true; - break; - case ',': - output.append(ch); - if (!quoteOpened) { - output.append(NEW_LINE); - appendIndent(output, depth); - } - break; - case ':': - if (quoteOpened) output.append(ch); - else output.append(" : "); - break; - default: - if (quoteOpened || !(ch == ' ')) - output.append(ch); - break; + switch (mode) { + case MODE_BETWEEN: + switch (ch) { + case '{': + case '[': + output.append(ch); + output.append(NEW_LINE); + appendIndent(output, ++depth); + break; + case '}': + case ']': + output.append(NEW_LINE); + appendIndent(output, --depth); + output.append(ch); + break; + case ',': + output.append(ch); + output.append(NEW_LINE); + appendIndent(output, depth); + break; + case ':': + output.append(" : "); + break; + case '\'': + output.append(ch); + mode = MODE_SINGLE; + break; + case '"': + output.append(ch); + mode = MODE_DOUBLE; + break; + case ' ': + break; + default: + output.append(ch); + break; + } + break; + case MODE_ESCAPE_SINGLE: + output.append(ch); + mode = MODE_SINGLE; + break; + case MODE_ESCAPE_DOUBLE: + output.append(ch); + mode = MODE_DOUBLE; + break; + case MODE_SINGLE: + output.append(ch); + switch (ch) { + case '\'': + mode = MODE_BETWEEN; + break; + case '\\': + mode = MODE_ESCAPE_SINGLE; + break; + } + break; + case MODE_DOUBLE: + output.append(ch); + switch (ch) { + case '"': + mode = MODE_BETWEEN; + break; + case '\\': + mode = MODE_ESCAPE_DOUBLE; + break; + } + break; } } return output.toString(); } -} \ No newline at end of file +}