Skip to content

Commit

Permalink
Fix #1702: Gson.toJson creates CharSequence which does not implement …
Browse files Browse the repository at this point in the history
…toString
  • Loading branch information
Marcono1234 committed May 21, 2020
1 parent ceae88b commit ebe8e5a
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 11 deletions.
28 changes: 21 additions & 7 deletions gson/src/main/java/com/google/gson/internal/Streams.java
Expand Up @@ -89,7 +89,7 @@ private static final class AppendableWriter extends Writer {
}

@Override public void write(char[] chars, int offset, int length) throws IOException {
currentWrite.chars = chars;
currentWrite.setChars(chars);
appendable.append(currentWrite, offset, offset + length);
}

Expand All @@ -103,18 +103,32 @@ private static final class AppendableWriter extends Writer {
/**
* A mutable char sequence pointing at a single char[].
*/
static class CurrentWrite implements CharSequence {
char[] chars;
public int length() {
private static class CurrentWrite implements CharSequence {
private char[] chars;
private String cachedString;

public void setChars(char[] chars) {
this.chars = chars;
this.cachedString = null;
}

@Override public int length() {
return chars.length;
}
public char charAt(int i) {
@Override public char charAt(int i) {
return chars[i];
}
public CharSequence subSequence(int start, int end) {
@Override public CharSequence subSequence(int start, int end) {
return new String(chars, start, end - start);
}

// Must return string representation to satisfy toString() contract
@Override public String toString() {
if (cachedString == null) {
cachedString = new String(chars);
}
return cachedString;
}
}
}

}
Expand Up @@ -22,6 +22,8 @@
import com.google.gson.common.TestTypes.BagOfPrimitives;

import com.google.gson.reflect.TypeToken;

import java.util.Arrays;
import java.util.Map;
import junit.framework.TestCase;

Expand Down Expand Up @@ -89,8 +91,8 @@ public void testTopLevelNullObjectDeserializationWithReaderAndSerializeNulls() {
}

public void testReadWriteTwoStrings() throws IOException {
Gson gson= new Gson();
CharArrayWriter writer= new CharArrayWriter();
Gson gson = new Gson();
CharArrayWriter writer = new CharArrayWriter();
writer.write(gson.toJson("one").toCharArray());
writer.write(gson.toJson("two").toCharArray());
CharArrayReader reader = new CharArrayReader(writer.toCharArray());
Expand All @@ -102,8 +104,8 @@ public void testReadWriteTwoStrings() throws IOException {
}

public void testReadWriteTwoObjects() throws IOException {
Gson gson= new Gson();
CharArrayWriter writer= new CharArrayWriter();
Gson gson = new Gson();
CharArrayWriter writer = new CharArrayWriter();
BagOfPrimitives expectedOne = new BagOfPrimitives(1, 1, true, "one");
writer.write(gson.toJson(expectedOne).toCharArray());
BagOfPrimitives expectedTwo = new BagOfPrimitives(2, 2, false, "two");
Expand Down Expand Up @@ -132,4 +134,45 @@ public void testTypeMismatchThrowsJsonSyntaxExceptionForReaders() {
} catch (JsonSyntaxException expected) {
}
}

/**
* Verifies that passing an {@link Appendable} which is not an instance of {@link Writer}
* to {@code Gson.toJson} works correctly.
*/
public void testToJsonAppendable() {
class CustomAppendable implements Appendable {
final StringBuilder stringBuilder = new StringBuilder();

@Override
public Appendable append(char c) throws IOException {
stringBuilder.append(c);
return this;
}

@Override
public Appendable append(CharSequence csq) throws IOException {
if (csq == null) {
append("null");
} else {
append(csq, 0, csq.length());
}
return this;
}

public Appendable append(CharSequence csq, int start, int end) throws IOException {
if (csq == null) {
return append("null");
}

// According to doc, toString() must return string representation
String s = csq.toString();
stringBuilder.append(s, start, end);
return this;
}
}

CustomAppendable appendable = new CustomAppendable();
gson.toJson(Arrays.asList("test", 123, true), appendable);
assertEquals("[\"test\",123,true]", appendable.stringBuilder.toString());
}
}

0 comments on commit ebe8e5a

Please sign in to comment.