diff --git a/gson/src/main/java/com/google/gson/Escaper.java b/gson/src/main/java/com/google/gson/Escaper.java index bb880a20..653738e1 100644 --- a/gson/src/main/java/com/google/gson/Escaper.java +++ b/gson/src/main/java/com/google/gson/Escaper.java @@ -36,32 +36,35 @@ import java.util.Set; */ class Escaper { - static final char[] HEX_CHARS = { + private static final char[] HEX_CHARS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; private static final Set JS_ESCAPE_CHARS; + private static final Set HTML_ESCAPE_CHARS; static { - Set tmpSet = new HashSet(); - tmpSet.add('\u0000'); - tmpSet.add('\r'); - tmpSet.add('\n'); - tmpSet.add('\u2028'); - tmpSet.add('\u2029'); - tmpSet.add('\u0085'); - tmpSet.add('\''); - tmpSet.add('"'); - tmpSet.add('<'); - tmpSet.add('>'); - tmpSet.add('&'); - tmpSet.add('='); - tmpSet.add('/'); - tmpSet.add('\\'); - JS_ESCAPE_CHARS = Collections.unmodifiableSet(tmpSet); + Set mandatoryEscapeSet = new HashSet(); + mandatoryEscapeSet.add('"'); + mandatoryEscapeSet.add('\\'); + JS_ESCAPE_CHARS = Collections.unmodifiableSet(mandatoryEscapeSet); + + Set htmlEscapeSet = new HashSet(); + htmlEscapeSet.add('<'); + htmlEscapeSet.add('>'); + htmlEscapeSet.add('&'); + htmlEscapeSet.add('='); + // htmlEscapeSet.add('/'); -- Removing slash for now since it causes some incompatibilities + HTML_ESCAPE_CHARS = Collections.unmodifiableSet(htmlEscapeSet); } - public static String escapeJsonString(CharSequence plainText) { + private final boolean escapeHtmlCharacters; + + Escaper(boolean escapeHtmlCharacters) { + this.escapeHtmlCharacters = escapeHtmlCharacters; + } + + public String escapeJsonString(CharSequence plainText) { StringBuffer escapedString = new StringBuffer(plainText.length() + 20); try { escapeJsonString(plainText, escapedString); @@ -71,54 +74,62 @@ class Escaper { return escapedString.toString(); } - private static void escapeJsonString(CharSequence plainText, StringBuffer out) throws IOException { + private void escapeJsonString(CharSequence plainText, StringBuffer out) throws IOException { int pos = 0; // Index just past the last char in plainText written to out. int len = plainText.length(); - for (int charCount, i = 0; i < len; i += charCount) { - int codePoint = Character.codePointAt(plainText, i); - charCount = Character.charCount(codePoint); + + for (int charCount, i = 0; i < len; i += charCount) { + int codePoint = Character.codePointAt(plainText, i); + charCount = Character.charCount(codePoint); + + if (!isControlCharacter(codePoint) && !mustEscapeCharInJsString(codePoint)) { + continue; + } - if (!isControlCharacter(codePoint) && !mustEscapeCharInJsString(codePoint)) { - continue; - } - - out.append(plainText, pos, i); - pos = i + charCount; - switch (codePoint) { - case '\b': - out.append("\\b"); - break; - case '\t': - out.append("\\t"); - break; - case '\n': - out.append("\\n"); - break; - case '\f': - out.append("\\f"); - break; - case '\r': - out.append("\\r"); - break; - case '\\': - out.append("\\\\"); - break; - case '/': - out.append("\\/"); - break; - case '"': - out.append('\\').append((char) codePoint); - break; - case '\'': - out.append((char) codePoint); - break; - default: - appendHexJavaScriptRepresentation(codePoint, out); - break; - } + out.append(plainText, pos, i); + pos = i + charCount; + switch (codePoint) { + case '\b': + out.append("\\b"); + break; + case '\t': + out.append("\\t"); + break; + case '\n': + out.append("\\n"); + break; + case '\f': + out.append("\\f"); + break; + case '\r': + out.append("\\r"); + break; + case '\\': + out.append("\\\\"); + break; + case '/': + out.append("\\/"); + break; + case '"': + out.append('\\').append((char) codePoint); + break; + default: + appendHexJavaScriptRepresentation(codePoint, out); + break; + } } out.append(plainText, pos, len); } + + private boolean mustEscapeCharInJsString(int codepoint) { + if (!Character.isSupplementaryCodePoint(codepoint)) { + char c = (char) codepoint; + return JS_ESCAPE_CHARS.contains(c) + || (escapeHtmlCharacters && HTML_ESCAPE_CHARS.contains(c)); + } else { + return false; + } + } private static boolean isControlCharacter(int codePoint) { // JSON spec defines these code points as control characters, so they must be escaped @@ -146,12 +157,4 @@ class Escaper { .append(HEX_CHARS[(codePoint >>> 4) & 0xf]) .append(HEX_CHARS[codePoint & 0xf]); } - - private static boolean mustEscapeCharInJsString(int codepoint) { - if (!Character.isSupplementaryCodePoint(codepoint)) { - return JS_ESCAPE_CHARS.contains((char)codepoint); - } else { - return false; - } - } } diff --git a/gson/src/main/java/com/google/gson/GsonBuilder.java b/gson/src/main/java/com/google/gson/GsonBuilder.java index b7dc5f1d..9b88e5ad 100644 --- a/gson/src/main/java/com/google/gson/GsonBuilder.java +++ b/gson/src/main/java/com/google/gson/GsonBuilder.java @@ -206,6 +206,31 @@ public final class GsonBuilder { setFormatter(new JsonPrintFormatter()); return this; } + + /** + * Configures Gson to output Json that fits in a page for pretty printing. This option only + * affects Json serialization. + * + * @param escapeHtmlChars true if specific HTML characters should be escaped + * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern + * @since 1.3 + */ + public GsonBuilder setPrettyPrinting(boolean escapeHtmlChars) { + setFormatter(new JsonPrintFormatter(escapeHtmlChars)); + return this; + } + + /** + * Configures Gson to output Json in a compact format. + * + * @param escapeHtmlChars true if specific HTML characters should be escaped + * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern + * @since 1.3 + */ + public GsonBuilder setCompactPrinting(boolean escapeHtmlChars) { + setFormatter(new JsonCompactFormatter(escapeHtmlChars)); + return this; + } /** * Configures Gson with a new formatting strategy other than the default strategy. The default diff --git a/gson/src/main/java/com/google/gson/JsonCompactFormatter.java b/gson/src/main/java/com/google/gson/JsonCompactFormatter.java index 561a2bb0..3b404d9e 100644 --- a/gson/src/main/java/com/google/gson/JsonCompactFormatter.java +++ b/gson/src/main/java/com/google/gson/JsonCompactFormatter.java @@ -124,14 +124,24 @@ final class JsonCompactFormatter implements JsonFormatter { writer.append('}'); } } + + private final boolean escapeHtmlChars; + + JsonCompactFormatter() { + this(true); + } + + JsonCompactFormatter(boolean escapeHtmlChars) { + this.escapeHtmlChars = escapeHtmlChars; + } public void format(JsonElement root, Appendable writer, boolean serializeNulls) throws IOException { if (root == null) { return; } - JsonElementVisitor visitor = - new JsonEscapingVisitor(new FormattingVisitor(writer, serializeNulls)); + JsonElementVisitor visitor = new JsonEscapingVisitor( + new FormattingVisitor(writer, serializeNulls), escapeHtmlChars); JsonTreeNavigator navigator = new JsonTreeNavigator(visitor, serializeNulls); navigator.navigate(root); } diff --git a/gson/src/main/java/com/google/gson/JsonEscapingVisitor.java b/gson/src/main/java/com/google/gson/JsonEscapingVisitor.java index 5f282a18..f2209ee2 100644 --- a/gson/src/main/java/com/google/gson/JsonEscapingVisitor.java +++ b/gson/src/main/java/com/google/gson/JsonEscapingVisitor.java @@ -25,14 +25,20 @@ import java.io.IOException; * @author Joel Leitch */ class JsonEscapingVisitor extends DelegatingJsonElementVisitor { + private final Escaper escaper; /** * Constructs a Visitor that will properly escape any JSON primitive values. * * @param delegate the JsonElementVisitor that this instance will use for delegation */ - protected JsonEscapingVisitor(JsonElementVisitor delegate) { + protected JsonEscapingVisitor(JsonElementVisitor delegate, boolean escapeHtmlChars) { + this(delegate, new Escaper(escapeHtmlChars)); + } + + protected JsonEscapingVisitor(JsonElementVisitor delegate, Escaper escaper) { super(delegate); + this.escaper = escaper; } @Override @@ -55,7 +61,7 @@ class JsonEscapingVisitor extends DelegatingJsonElementVisitor { private JsonPrimitive escapeJsonPrimitive(JsonPrimitive member) { if (member.isString()) { String memberValue = member.getAsString(); - String escapedValue = Escaper.escapeJsonString(memberValue); + String escapedValue = escaper.escapeJsonString(memberValue); if (!escapedValue.equals(memberValue)) { member.setValue(escapedValue); } diff --git a/gson/src/main/java/com/google/gson/JsonPrintFormatter.java b/gson/src/main/java/com/google/gson/JsonPrintFormatter.java index 6f747fd4..b7f26f1a 100644 --- a/gson/src/main/java/com/google/gson/JsonPrintFormatter.java +++ b/gson/src/main/java/com/google/gson/JsonPrintFormatter.java @@ -32,19 +32,26 @@ final class JsonPrintFormatter implements JsonFormatter { private final int printMargin; private final int indentationSize; private final int rightMargin; + private final boolean escapeHtmlChars; public static final int DEFAULT_PRINT_MARGIN = 80; public static final int DEFAULT_INDENTATION_SIZE = 2; public static final int DEFAULT_RIGHT_MARGIN = 4; - public JsonPrintFormatter() { - this(DEFAULT_PRINT_MARGIN, DEFAULT_INDENTATION_SIZE, DEFAULT_RIGHT_MARGIN); + JsonPrintFormatter() { + this(true); + } + + JsonPrintFormatter(boolean escapeHtmlChars) { + this(DEFAULT_PRINT_MARGIN, DEFAULT_INDENTATION_SIZE, DEFAULT_RIGHT_MARGIN, escapeHtmlChars); } - public JsonPrintFormatter(int printMargin, int indentationSize, int rightMargin) { + JsonPrintFormatter(int printMargin, int indentationSize, int rightMargin, + boolean escapeHtmlChars) { this.printMargin = printMargin; this.indentationSize = indentationSize; this.rightMargin = rightMargin; + this.escapeHtmlChars = escapeHtmlChars; } private class JsonWriter { @@ -234,8 +241,8 @@ final class JsonPrintFormatter implements JsonFormatter { return; } JsonWriter jsonWriter = new JsonWriter(writer); - JsonElementVisitor visitor = - new JsonEscapingVisitor(new PrintFormattingVisitor(jsonWriter, serializeNulls)); + JsonElementVisitor visitor = new JsonEscapingVisitor( + new PrintFormattingVisitor(jsonWriter, serializeNulls), escapeHtmlChars); JsonTreeNavigator navigator = new JsonTreeNavigator(visitor, serializeNulls); navigator.navigate(root); jsonWriter.finishLine(); diff --git a/gson/src/main/java/com/google/gson/TestCharacters.java b/gson/src/main/java/com/google/gson/TestCharacters.java new file mode 100644 index 00000000..ae22b544 --- /dev/null +++ b/gson/src/main/java/com/google/gson/TestCharacters.java @@ -0,0 +1,12 @@ +package com.google.gson; + +public class TestCharacters { + + public static void main(String[] args) { + System.out.println("\\b: " + Character.codePointAt("\b", 0)); + System.out.println("\\r: " + Character.codePointAt("\r", 0)); + System.out.println("\\n: " + Character.codePointAt("\n", 0)); + System.out.println("\\t: " + Character.codePointAt("\t", 0)); + System.out.println("': " + Character.codePointAt("'", 0)); + } +} diff --git a/gson/src/test/java/com/google/gson/EscaperTest.java b/gson/src/test/java/com/google/gson/EscaperTest.java index eaa8d50f..8565ddef 100644 --- a/gson/src/test/java/com/google/gson/EscaperTest.java +++ b/gson/src/test/java/com/google/gson/EscaperTest.java @@ -25,52 +25,62 @@ import junit.framework.TestCase; */ public class EscaperTest extends TestCase { + private Escaper escapeHtmlChar; + private Escaper noEscapeHtmlChar; + + @Override + protected void setUp() throws Exception { + super.setUp(); + escapeHtmlChar = new Escaper(true); + noEscapeHtmlChar = new Escaper(false); + } + public void testNoSpecialCharacters() { String value = "Testing123"; - String escapedString = Escaper.escapeJsonString(value); + String escapedString = escapeHtmlChar.escapeJsonString(value); assertEquals(value, escapedString); } public void testNewlineEscaping() throws Exception { String containsNewline = "123\n456"; - String escapedString = Escaper.escapeJsonString(containsNewline); + String escapedString = escapeHtmlChar.escapeJsonString(containsNewline); assertEquals("123\\n456", escapedString); } public void testCarrageReturnEscaping() throws Exception { String containsCarrageReturn = "123\r456"; - String escapedString = Escaper.escapeJsonString(containsCarrageReturn); + String escapedString = escapeHtmlChar.escapeJsonString(containsCarrageReturn); assertEquals("123\\r456", escapedString); } public void testTabEscaping() throws Exception { String containsTab = "123\t456"; - String escapedString = Escaper.escapeJsonString(containsTab); + String escapedString = escapeHtmlChar.escapeJsonString(containsTab); assertEquals("123\\t456", escapedString); } public void testQuoteEscaping() throws Exception { String containsQuote = "123\"456"; - String escapedString = Escaper.escapeJsonString(containsQuote); + String escapedString = escapeHtmlChar.escapeJsonString(containsQuote); assertEquals("123\\\"456", escapedString); } public void testLineSeparatorEscaping() throws Exception { String src = "123\u2028 456"; - String escapedString = Escaper.escapeJsonString(src); + String escapedString = escapeHtmlChar.escapeJsonString(src); assertEquals("123\\u2028 456", escapedString); } public void testParagraphSeparatorEscaping() throws Exception { String src = "123\u2029 456"; - String escapedString = Escaper.escapeJsonString(src); + String escapedString = escapeHtmlChar.escapeJsonString(src); assertEquals("123\\u2029 456", escapedString); } public void testControlCharBlockEscaping() throws Exception { for (char c = '\u007f'; c <= '\u009f'; ++c) { String src = "123 " + c + " 456"; - String escapedString = Escaper.escapeJsonString(src); + String escapedString = escapeHtmlChar.escapeJsonString(src); assertFalse(src.equals(escapedString)); } } @@ -79,8 +89,11 @@ public class EscaperTest extends TestCase { String containsEquals = "123=456"; int index = containsEquals.indexOf('='); String unicodeValue = convertToUnicodeString(Character.codePointAt(containsEquals, index)); - String escapedString = Escaper.escapeJsonString(containsEquals); + String escapedString = escapeHtmlChar.escapeJsonString(containsEquals); assertEquals("123" + unicodeValue + "456", escapedString); + + escapedString = noEscapeHtmlChar.escapeJsonString(containsEquals); + assertEquals(containsEquals, escapedString); } public void testGreaterThanAndLessThanEscaping() throws Exception { @@ -90,8 +103,11 @@ public class EscaperTest extends TestCase { String gtAsUnicode = convertToUnicodeString(Character.codePointAt(containsLtGt, gtIndex)); String ltAsUnicode = convertToUnicodeString(Character.codePointAt(containsLtGt, ltIndex)); - String escapedString = Escaper.escapeJsonString(containsLtGt); + String escapedString = escapeHtmlChar.escapeJsonString(containsLtGt); assertEquals("123" + gtAsUnicode + "456" + ltAsUnicode, escapedString); + + escapedString = noEscapeHtmlChar.escapeJsonString(containsLtGt); + assertEquals(containsLtGt, escapedString); } public void testAmpersandEscaping() throws Exception { @@ -99,24 +115,30 @@ public class EscaperTest extends TestCase { int ampIndex = containsAmp.indexOf('&'); String ampAsUnicode = convertToUnicodeString(Character.codePointAt(containsAmp, ampIndex)); - String escapedString = Escaper.escapeJsonString(containsAmp); + String escapedString = escapeHtmlChar.escapeJsonString(containsAmp); assertEquals("123" + ampAsUnicode + "456", escapedString); + + escapedString = noEscapeHtmlChar.escapeJsonString(containsAmp); + assertEquals(containsAmp, escapedString); char ampCharAsUnicode = '\u0026'; String containsAmpUnicode = "123" + ampCharAsUnicode + "456"; - escapedString = Escaper.escapeJsonString(containsAmpUnicode); + escapedString = escapeHtmlChar.escapeJsonString(containsAmpUnicode); assertEquals("123" + ampAsUnicode + "456", escapedString); + + escapedString = noEscapeHtmlChar.escapeJsonString(containsAmpUnicode); + assertEquals(containsAmp, escapedString); } public void testSlashEscaping() throws Exception { String containsSlash = "123\\456"; - String escapedString = Escaper.escapeJsonString(containsSlash); + String escapedString = escapeHtmlChar.escapeJsonString(containsSlash); assertEquals("123\\\\456", escapedString); } public void testSingleQuoteNotEscaped() throws Exception { String containsSingleQuote = "123'456"; - String escapedString = Escaper.escapeJsonString(containsSingleQuote); + String escapedString = escapeHtmlChar.escapeJsonString(containsSingleQuote); assertEquals(containsSingleQuote, escapedString); } @@ -124,7 +146,7 @@ public class EscaperTest extends TestCase { char unicodeChar = '\u2028'; String unicodeString = "Testing" + unicodeChar; - String escapedString = Escaper.escapeJsonString(unicodeString); + String escapedString = escapeHtmlChar.escapeJsonString(unicodeString); assertFalse(unicodeString.equals(escapedString)); assertEquals("Testing\\u2028", escapedString); } @@ -132,7 +154,7 @@ public class EscaperTest extends TestCase { public void testUnicodeCharacterStringNoEscaping() throws Exception { String unicodeString = "\u0065\u0066"; - String escapedString = Escaper.escapeJsonString(unicodeString); + String escapedString = escapeHtmlChar.escapeJsonString(unicodeString); assertEquals(unicodeString, escapedString); } diff --git a/gson/src/test/java/com/google/gson/FunctionalWithInternalDependenciesTest.java b/gson/src/test/java/com/google/gson/FunctionalWithInternalDependenciesTest.java index 7e292d6b..44540f4f 100644 --- a/gson/src/test/java/com/google/gson/FunctionalWithInternalDependenciesTest.java +++ b/gson/src/test/java/com/google/gson/FunctionalWithInternalDependenciesTest.java @@ -60,7 +60,8 @@ public class FunctionalWithInternalDependenciesTest extends TestCase { } public void testPrettyPrintList() { - JsonFormatter formatter = new JsonPrintFormatter(PRINT_MARGIN, INDENTATION_SIZE, RIGHT_MARGIN); + JsonFormatter formatter = new JsonPrintFormatter( + PRINT_MARGIN, INDENTATION_SIZE, RIGHT_MARGIN, true); Gson gson = builder.setFormatter(formatter).create(); BagOfPrimitives b = new BagOfPrimitives(); List listOfB = new LinkedList(); @@ -74,7 +75,8 @@ public class FunctionalWithInternalDependenciesTest extends TestCase { } public void testPrettyPrintArrayOfObjects() { - JsonFormatter formatter = new JsonPrintFormatter(PRINT_MARGIN, INDENTATION_SIZE, RIGHT_MARGIN); + JsonFormatter formatter = new JsonPrintFormatter( + PRINT_MARGIN, INDENTATION_SIZE, RIGHT_MARGIN, true); Gson gson = builder.setFormatter(formatter).create(); ArrayOfObjects target = new ArrayOfObjects(); String json = gson.toJson(target); @@ -83,7 +85,8 @@ public class FunctionalWithInternalDependenciesTest extends TestCase { } public void testPrettyPrintArrayOfPrimitives() { - JsonFormatter formatter = new JsonPrintFormatter(PRINT_MARGIN, INDENTATION_SIZE, RIGHT_MARGIN); + JsonFormatter formatter = new JsonPrintFormatter( + PRINT_MARGIN, INDENTATION_SIZE, RIGHT_MARGIN, true); Gson gson = builder.setFormatter(formatter).create(); int[] ints = new int[] { 1, 2, 3, 4, 5 }; String json = gson.toJson(ints); @@ -91,7 +94,8 @@ public class FunctionalWithInternalDependenciesTest extends TestCase { } public void testPrettyPrintArrayOfPrimitiveArrays() { - JsonFormatter formatter = new JsonPrintFormatter(PRINT_MARGIN, INDENTATION_SIZE, RIGHT_MARGIN); + JsonFormatter formatter = new JsonPrintFormatter( + PRINT_MARGIN, INDENTATION_SIZE, RIGHT_MARGIN, true); Gson gson = builder.setFormatter(formatter).create(); int[][] ints = new int[][] { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 }, { 9, 0 }, { 10 } }; String json = gson.toJson(ints); @@ -99,7 +103,8 @@ public class FunctionalWithInternalDependenciesTest extends TestCase { } public void testPrettyPrintListOfPrimitiveArrays() { - JsonFormatter formatter = new JsonPrintFormatter(PRINT_MARGIN, INDENTATION_SIZE, RIGHT_MARGIN); + JsonFormatter formatter = new JsonPrintFormatter( + PRINT_MARGIN, INDENTATION_SIZE, RIGHT_MARGIN, true); Gson gson = builder.setFormatter(formatter).create(); List list = Arrays.asList(new Integer[][] { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 }, { 9, 0 }, { 10 } }); @@ -108,7 +113,8 @@ public class FunctionalWithInternalDependenciesTest extends TestCase { } public void testMultipleArrays() { - JsonFormatter formatter = new JsonPrintFormatter(PRINT_MARGIN, INDENTATION_SIZE, RIGHT_MARGIN); + JsonFormatter formatter = new JsonPrintFormatter( + PRINT_MARGIN, INDENTATION_SIZE, RIGHT_MARGIN, true); Gson gson = builder.setFormatter(formatter).create(); int[][][] ints = new int[][][] { { { 1 }, { 2 } } }; String json = gson.toJson(ints); diff --git a/gson/src/test/java/com/google/gson/JsonEscapingVisitorTest.java b/gson/src/test/java/com/google/gson/JsonEscapingVisitorTest.java index c88e6fb9..409cf335 100644 --- a/gson/src/test/java/com/google/gson/JsonEscapingVisitorTest.java +++ b/gson/src/test/java/com/google/gson/JsonEscapingVisitorTest.java @@ -26,12 +26,14 @@ import junit.framework.TestCase; public class JsonEscapingVisitorTest extends TestCase { private StubbedJsonElementVisitor stubVisitor; private JsonEscapingVisitor escapingVisitor; + private Escaper escaper; @Override protected void setUp() throws Exception { super.setUp(); stubVisitor = new StubbedJsonElementVisitor(); - escapingVisitor = new JsonEscapingVisitor(stubVisitor); + escaper = new Escaper(true); + escapingVisitor = new JsonEscapingVisitor(stubVisitor, escaper); } public void testNonStringPrimitiveVisitation() throws Exception { @@ -52,7 +54,7 @@ public class JsonEscapingVisitorTest extends TestCase { String value = "Testing\"123"; JsonPrimitive primitive = new JsonPrimitive(value); escapingVisitor.visitPrimitive(primitive); - assertEquals(Escaper.escapeJsonString(value), stubVisitor.primitiveReceived.getAsString()); + assertEquals(escaper.escapeJsonString(value), stubVisitor.primitiveReceived.getAsString()); } public void testNonStringArrayVisitation() throws Exception { @@ -79,7 +81,7 @@ public class JsonEscapingVisitorTest extends TestCase { JsonArray array = new JsonArray(); array.add(primitive); escapingVisitor.visitArrayMember(array, primitive, true); - assertEquals(Escaper.escapeJsonString(value), stubVisitor.primitiveReceived.getAsString()); + assertEquals(escaper.escapeJsonString(value), stubVisitor.primitiveReceived.getAsString()); } public void testNonStringFieldVisitation() throws Exception { @@ -112,7 +114,7 @@ public class JsonEscapingVisitorTest extends TestCase { object.addProperty(fieldName, value); escapingVisitor.visitObjectMember(object, fieldName, primitive, true); - assertEquals(Escaper.escapeJsonString(value), stubVisitor.primitiveReceived.getAsString()); + assertEquals(escaper.escapeJsonString(value), stubVisitor.primitiveReceived.getAsString()); } private static class StubbedJsonElementVisitor implements JsonElementVisitor { diff --git a/gson/src/test/java/com/google/gson/functional/DefaultTypeAdaptersTest.java b/gson/src/test/java/com/google/gson/functional/DefaultTypeAdaptersTest.java index 9f78a41a..00707847 100644 --- a/gson/src/test/java/com/google/gson/functional/DefaultTypeAdaptersTest.java +++ b/gson/src/test/java/com/google/gson/functional/DefaultTypeAdaptersTest.java @@ -52,7 +52,7 @@ public class DefaultTypeAdaptersTest extends TestCase { public void testUrlSerialization() throws Exception { String urlValue = "http://google.com/"; URL url = new URL(urlValue); - assertEquals("\"http:\\/\\/google.com\\/\"", gson.toJson(url)); + assertEquals("\"http://google.com/\"", gson.toJson(url)); } public void testUrlDeserialization() { @@ -60,6 +60,9 @@ public class DefaultTypeAdaptersTest extends TestCase { String json = "'http:\\/\\/google.com\\/'"; URL target = gson.fromJson(json, URL.class); assertEquals(urlValue, target.toExternalForm()); + + gson.fromJson('"' + urlValue + '"', URL.class); + assertEquals(urlValue, target.toExternalForm()); } public void testUrlNullSerialization() throws Exception { @@ -80,7 +83,7 @@ public class DefaultTypeAdaptersTest extends TestCase { public void testUriSerialization() throws Exception { String uriValue = "http://google.com/"; URI uri = new URI(uriValue); - assertEquals("\"http:\\/\\/google.com\\/\"", gson.toJson(uri)); + assertEquals("\"http://google.com/\"", gson.toJson(uri)); } public void testUriDeserialization() { diff --git a/gson/src/test/java/com/google/gson/functional/PrimitiveTest.java b/gson/src/test/java/com/google/gson/functional/PrimitiveTest.java index e0bb59e3..74e2dfd2 100644 --- a/gson/src/test/java/com/google/gson/functional/PrimitiveTest.java +++ b/gson/src/test/java/com/google/gson/functional/PrimitiveTest.java @@ -547,4 +547,14 @@ public class PrimitiveTest extends TestCase { value = gson.fromJson("\"25\"", long.class); assertEquals(25, value); } + + public void testHtmlCharacterSerialization() throws Exception { + String target = ""; + String result = gson.toJson(target); + assertFalse(result.equals('"' + target + '"')); + + gson = new GsonBuilder().setCompactPrinting(false).create(); + result = gson.toJson(target); + assertTrue(result.equals('"' + target + '"')); + } }