Complete the proper handling of all special characters in JSON strings for TJSONProtocol
Reviewed By: dreiss
Test Plan: test/java/TestClient
git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@665373 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/lib/java/src/TByteArrayOutputStream.java b/lib/java/src/TByteArrayOutputStream.java
new file mode 100644
index 0000000..94ce003
--- /dev/null
+++ b/lib/java/src/TByteArrayOutputStream.java
@@ -0,0 +1,29 @@
+// Copyright (c) 2006- Facebook
+// Distributed under the Thrift Software License
+//
+// See accompanying file LICENSE or visit the Thrift site at:
+// http://developers.facebook.com/thrift/
+
+package com.facebook.thrift;
+
+import java.io.ByteArrayOutputStream;
+
+/**
+ * Class that allows access to the underlying buf without doing deep
+ * copies on it.
+ *
+ * @author Mark Slee <mcslee@facebook.com>
+ */
+public class TByteArrayOutputStream extends ByteArrayOutputStream {
+ public TByteArrayOutputStream(int size) {
+ super(size);
+ }
+
+ public byte[] get() {
+ return buf;
+ }
+
+ public int len() {
+ return count;
+ }
+}
diff --git a/lib/java/src/protocol/TJSONProtocol.java b/lib/java/src/protocol/TJSONProtocol.java
index 07dee63..fefa65c 100644
--- a/lib/java/src/protocol/TJSONProtocol.java
+++ b/lib/java/src/protocol/TJSONProtocol.java
@@ -6,8 +6,10 @@
package com.facebook.thrift.protocol;
+import com.facebook.thrift.TByteArrayOutputStream;
import com.facebook.thrift.TException;
import com.facebook.thrift.transport.TTransport;
+import java.io.ByteArrayOutputStream;
import java.io.UnsupportedEncodingException;
import java.util.Stack;
@@ -30,11 +32,11 @@
public static final byte[] COMMA = new byte[] {','};
public static final byte[] COLON = new byte[] {':'};
- public static final byte[] QUOTE = new byte[] {'"'};
public static final byte[] LBRACE = new byte[] {'{'};
public static final byte[] RBRACE = new byte[] {'}'};
public static final byte[] LBRACKET = new byte[] {'['};
public static final byte[] RBRACKET = new byte[] {']'};
+ public static final char QUOTE = '"';
protected class Context {
protected void write() throws TException {}
@@ -208,26 +210,55 @@
public void writeString(String str) throws TException {
writeContext_.write();
- trans_.write(QUOTE);
-
int length = str.length();
- StringBuffer escape = new StringBuffer(length);
- char c;
+ StringBuffer escape = new StringBuffer(length + 16);
+ escape.append(QUOTE);
for (int i = 0; i < length; ++i) {
- c = str.charAt(i);
+ char c = str.charAt(i);
switch (c) {
case '"':
case '\\':
escape.append('\\');
escape.append(c);
break;
+ case '\b':
+ escape.append('\\');
+ escape.append('b');
+ break;
+ case '\f':
+ escape.append('\\');
+ escape.append('f');
+ break;
+ case '\n':
+ escape.append('\\');
+ escape.append('n');
+ break;
+ case '\r':
+ escape.append('\\');
+ escape.append('r');
+ break;
+ case '\t':
+ escape.append('\\');
+ escape.append('t');
+ break;
default:
- escape.append(c);
+ // Control characeters! According to JSON RFC u0020 (space)
+ if (c < ' ') {
+ String hex = Integer.toHexString(c);
+ escape.append('\\');
+ escape.append('u');
+ for (int j = 4; j > hex.length(); --j) {
+ escape.append('0');
+ }
+ escape.append(hex);
+ } else {
+ escape.append(c);
+ }
break;
}
}
+ escape.append(QUOTE);
_writeStringData(escape.toString());
- trans_.write(QUOTE);
}
public void writeBinary(byte[] bin) throws TException {
diff --git a/lib/java/src/transport/TFramedTransport.java b/lib/java/src/transport/TFramedTransport.java
index 9eb068d..7121c09 100644
--- a/lib/java/src/transport/TFramedTransport.java
+++ b/lib/java/src/transport/TFramedTransport.java
@@ -9,6 +9,8 @@
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
+import com.facebook.thrift.TByteArrayOutputStream;
+
/**
* Socket implementation of the TTransport interface. To be commented soon!
*
@@ -22,29 +24,11 @@
private TTransport transport_ = null;
/**
- * Class that allows access to the underlying buf without doing deep
- * copies on it.
- */
- private static class MyByteArrayOutputStream extends ByteArrayOutputStream {
- public MyByteArrayOutputStream(int size) {
- super(size);
- }
-
- public byte[] get() {
- return buf;
- }
-
- public int len() {
- return count;
- }
- }
-
- /**
* Buffer for output
*/
- private final MyByteArrayOutputStream writeBuffer_ =
- new MyByteArrayOutputStream(1024);
-
+ private final TByteArrayOutputStream writeBuffer_ =
+ new TByteArrayOutputStream(1024);
+
/**
* Buffer for input
*/
@@ -59,7 +43,7 @@
* Whether to frame output
*/
private boolean frameWrite_ = true;
-
+
/**
* Constructor wraps around another tranpsort
*/
@@ -135,7 +119,7 @@
}
writeBuffer_.write(buf, off, len);
}
-
+
public void flush() throws TTransportException {
if (!frameWrite_) {
transport_.flush();