support \0\1 ... \9

This commit is contained in:
wenshao
2013-06-23 14:19:41 +08:00
parent 3894ad3dd9
commit d11eec0663
14 changed files with 246 additions and 92 deletions
@@ -79,7 +79,6 @@ public abstract class JSON implements JSONStreamAware, JSONAware {
features |= com.alibaba.fastjson.serializer.SerializerFeature.SkipTransientField.getMask();
features |= com.alibaba.fastjson.serializer.SerializerFeature.WriteEnumUsingToString.getMask();
features |= com.alibaba.fastjson.serializer.SerializerFeature.SortField.getMask();
features |= com.alibaba.fastjson.serializer.SerializerFeature.WriteTabAsSpecial.getMask();
// features |=
// com.alibaba.fastjson.serializer.SerializerFeature.WriteSlashAsSpecial.getMask();
DEFAULT_GENERATE_FEATURE = features;
@@ -19,12 +19,10 @@ package com.alibaba.fastjson.parser;
* @author wenshao<szujobs@hotmail.com>
*/
public final class CharTypes {
public final static char[] digits = {
'0' , '1' , '2' , '3' , '4' , '5' ,
'6' , '7' , '8' , '9' , 'A' , 'B' ,
'C' , 'D' , 'E' , 'F'
};
public final static char[] digits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A',
'B', 'C', 'D', 'E', 'F' };
public final static boolean[] firstIdentifierFlags = new boolean[256];
static {
for (char c = 0; c < firstIdentifierFlags.length; ++c) {
@@ -63,70 +61,87 @@ public final class CharTypes {
public final static char[] replaceChars = new char[128];
static {
specicalFlags_doubleQuotes['\b'] = true;
specicalFlags_doubleQuotes['\n'] = true;
specicalFlags_doubleQuotes['\0'] = true;
specicalFlags_doubleQuotes['\1'] = true;
specicalFlags_doubleQuotes['\2'] = true;
specicalFlags_doubleQuotes['\3'] = true;
specicalFlags_doubleQuotes['\4'] = true;
specicalFlags_doubleQuotes['\5'] = true;
specicalFlags_doubleQuotes['\6'] = true;
specicalFlags_doubleQuotes['\7'] = true;
specicalFlags_doubleQuotes['\b'] = true; // 8
specicalFlags_doubleQuotes['\t'] = true; // 9
specicalFlags_doubleQuotes['\n'] = true; // 10
specicalFlags_doubleQuotes['\u000B'] = true; // 11
specicalFlags_doubleQuotes['\f'] = true;
specicalFlags_doubleQuotes['\r'] = true;
specicalFlags_doubleQuotes['\"'] = true;
specicalFlags_doubleQuotes['\\'] = true;
specicalFlags_doubleQuotes['\u000B'] = true;
specicalFlags_singleQuotes['\b'] = true;
specicalFlags_singleQuotes['\n'] = true;
specicalFlags_singleQuotes['\f'] = true;
specicalFlags_singleQuotes['\0'] = true;
specicalFlags_singleQuotes['\1'] = true;
specicalFlags_singleQuotes['\2'] = true;
specicalFlags_singleQuotes['\3'] = true;
specicalFlags_singleQuotes['\4'] = true;
specicalFlags_singleQuotes['\5'] = true;
specicalFlags_singleQuotes['\6'] = true;
specicalFlags_singleQuotes['\7'] = true;
specicalFlags_singleQuotes['\b'] = true; // 8
specicalFlags_singleQuotes['\t'] = true; // 9
specicalFlags_singleQuotes['\n'] = true; // 10
specicalFlags_singleQuotes['\u000B'] = true; // 11
specicalFlags_singleQuotes['\f'] = true; // 12
specicalFlags_singleQuotes['\r'] = true;
specicalFlags_singleQuotes['\''] = true;
specicalFlags_singleQuotes['\\'] = true;
specicalFlags_singleQuotes['\u000B'] = true;
replaceChars['\b'] = 'b';
replaceChars['\n'] = 'n';
replaceChars['\f'] = 'f';
replaceChars['\r'] = 'r';
replaceChars['\"'] = '"';
replaceChars['\''] = '\'';
replaceChars['\\'] = '\\';
replaceChars['\t'] = 't';
replaceChars['/'] = '/';
replaceChars['\u000B'] = 'v';
replaceChars['\0'] = '0';
replaceChars['\1'] = '1';
replaceChars['\2'] = '2';
replaceChars['\3'] = '3';
replaceChars['\4'] = '4';
replaceChars['\5'] = '5';
replaceChars['\6'] = '6';
replaceChars['\7'] = '7';
replaceChars['\b'] = 'b'; // 8
replaceChars['\t'] = 't'; // 9
replaceChars['\n'] = 'n'; // 10
replaceChars['\u000B'] = 'v'; // 11
replaceChars['\f'] = 'f'; // 12
replaceChars['\r'] = 'r'; // 13
replaceChars['\"'] = '"'; // 34
replaceChars['\''] = '\''; // 39
replaceChars['/'] = '/'; // 47
replaceChars['\\'] = '\\'; // 92
}
public final static char [] ASCII_CHARS = {
'0', '0', '0', '1', '0', '2', '0', '3',
'0', '4', '0', '5', '0', '6', '0', '7',
'0', '8', '0', '9', '0', 'A', '0', 'B',
'0', 'C', '0', 'D', '0', 'E', '0', 'F',
'1', '0', '1', '1', '1', '2', '1', '3',
'1', '4', '1', '5', '1', '6', '1', '7',
'1', '8', '1', '9', '1', 'A', '1', 'B',
'1', 'C', '1', 'D', '1', 'E', '1', 'F',
'2', '0', '2', '1', '2', '2', '2', '3',
'2', '4', '2', '5', '2', '6', '2', '7',
'2', '8', '2', '9', '2', 'A', '2', 'B',
'2', 'C', '2', 'D', '2', 'E', '2', 'F',
} ;
public final static char[] ASCII_CHARS = { '0', '0', '0', '1', '0', '2', '0', '3', '0', '4', '0', '5', '0', '6',
'0', '7', '0', '8', '0', '9', '0', 'A', '0', 'B', '0', 'C', '0', 'D', '0', 'E', '0', 'F', '1', '0', '1',
'1', '1', '2', '1', '3', '1', '4', '1', '5', '1', '6', '1', '7', '1', '8', '1', '9', '1', 'A', '1', 'B',
'1', 'C', '1', 'D', '1', 'E', '1', 'F', '2', '0', '2', '1', '2', '2', '2', '3', '2', '4', '2', '5', '2',
'6', '2', '7', '2', '8', '2', '9', '2', 'A', '2', 'B', '2', 'C', '2', 'D', '2', 'E', '2', 'F', };
public final static boolean isEmoji(char ch) {
if (ch >= '\uE001' && ch <= '\uE05A') {
return true;
}
if (ch >= '\uE101' && ch <= '\uE15A') {
return true;
}
if (ch >= '\uE201' && ch <= '\uE253') {
return true;
}
if (ch >= '\uE401' && ch <= '\uE44C') {
return true;
}
if (ch >= '\uE501' && ch <= '\uE537') {
return true;
}
return false;
}
}
@@ -1404,30 +1404,60 @@ public final class JSONScanner extends JSONLexer {
ch = charAt(++bp);
switch (ch) {
case '"':
putChar('"');
case '0':
putChar('\0');
break;
case '\\':
putChar('\\');
case '1':
putChar('\1');
break;
case '/':
putChar('/');
case '2':
putChar('\2');
break;
case 'b':
case '3':
putChar('\3');
break;
case '4':
putChar('\4');
break;
case '5':
putChar('\5');
break;
case '6':
putChar('\6');
break;
case '7':
putChar('\7');
break;
case 'b': // 8
putChar('\b');
break;
case 'f':
case 't': // 9
putChar('\t');
break;
case 'n': // 10
putChar('\n');
break;
case 'v': // 11
putChar('\u000B');
break;
case 'f': // 12
case 'F':
putChar('\f');
break;
case 'n':
putChar('\n');
break;
case 'r':
case 'r': // 13
putChar('\r');
break;
case 't':
putChar('\t');
case '"': // 34
putChar('"');
break;
case '\'': // 39
putChar('\'');
break;
case '/': // 47
putChar('/');
break;
case '\\': // 92
putChar('\\');
break;
case 'x':
char x1 = ch = charAt(++bp);
@@ -587,7 +587,6 @@ public final class SerializeWriter extends Writer {
} else {
if (ch < CharTypes.specicalFlags_doubleQuotes.length
&& CharTypes.specicalFlags_doubleQuotes[ch] //
|| (ch == '\t' && isEnabled(SerializerFeature.WriteTabAsSpecial))
|| (ch == '/' && isEnabled(SerializerFeature.WriteSlashAsSpecial))) {
write('\\');
write(replaceChars[(int) ch]);
@@ -723,9 +722,7 @@ public final class SerializeWriter extends Writer {
continue;
}
if (ch < CharTypes.specicalFlags_doubleQuotes.length
&& CharTypes.specicalFlags_doubleQuotes[ch] //
|| (ch == '\t' && isEnabled(SerializerFeature.WriteTabAsSpecial))
if (ch < CharTypes.specicalFlags_doubleQuotes.length && CharTypes.specicalFlags_doubleQuotes[ch] //
|| (ch == '/' && isEnabled(SerializerFeature.WriteSlashAsSpecial))) {
specialCount++;
lastSpecialIndex = i;
@@ -754,9 +751,7 @@ public final class SerializeWriter extends Writer {
for (int i = textIndex; i < text.length(); ++i) {
char ch = text.charAt(i);
if (ch < CharTypes.specicalFlags_doubleQuotes.length
&& CharTypes.specicalFlags_doubleQuotes[ch] //
|| (ch == '\t' && isEnabled(SerializerFeature.WriteTabAsSpecial))
if (ch < CharTypes.specicalFlags_doubleQuotes.length && CharTypes.specicalFlags_doubleQuotes[ch] //
|| (ch == '/' && isEnabled(SerializerFeature.WriteSlashAsSpecial))) {
buf[bufIndex++] = '\\';
buf[bufIndex++] = replaceChars[(int) ch];
@@ -1142,7 +1137,6 @@ public final class SerializeWriter extends Writer {
if (ch < CharTypes.specicalFlags_doubleQuotes.length
&& CharTypes.specicalFlags_doubleQuotes[ch] //
|| (ch == '\t' && isEnabled(SerializerFeature.WriteTabAsSpecial))
|| (ch == '/' && isEnabled(SerializerFeature.WriteSlashAsSpecial))) {
buf[bufIndex++] = '\\';
buf[bufIndex++] = replaceChars[(int) ch];
@@ -1175,8 +1169,7 @@ public final class SerializeWriter extends Writer {
return false;
}
if (ch == '\b' || ch == '\n' || ch == '\r' || ch == '\f' || ch == '\\' || ch == '"' //
|| (ch == '\t' && SerializerFeature.isEnabled(features, SerializerFeature.WriteTabAsSpecial))) {
if (ch <= 13 || ch == '\\' || ch == '"') {
return true;
}
@@ -1252,9 +1245,7 @@ public final class SerializeWriter extends Writer {
write('\'');
for (int i = 0; i < text.length(); ++i) {
char ch = text.charAt(i);
if (ch == '\b' || ch == '\n' || ch == '\r' || ch == '\f' || ch == '\\'
|| ch == '\'' //
|| (ch == '\t' && isEnabled(SerializerFeature.WriteTabAsSpecial))
if (ch <= 13 || ch == '\\' || ch == '\'' //
|| (ch == '/' && isEnabled(SerializerFeature.WriteSlashAsSpecial))) {
write('\\');
write(replaceChars[(int) ch]);
@@ -1280,9 +1271,7 @@ public final class SerializeWriter extends Writer {
char lastSpecial = '\0';
for (int i = start; i < end; ++i) {
char ch = buf[i];
if (ch == '\b' || ch == '\n' || ch == '\r' || ch == '\f' || ch == '\\'
|| ch == '\'' //
|| (ch == '\t' && isEnabled(SerializerFeature.WriteTabAsSpecial))
if (ch <= 13 || ch == '\\' || ch == '\'' //
|| (ch == '/' && isEnabled(SerializerFeature.WriteSlashAsSpecial))) {
specialCount++;
lastSpecialIndex = i;
@@ -1308,9 +1297,7 @@ public final class SerializeWriter extends Writer {
for (int i = lastSpecialIndex - 2; i >= start; --i) {
char ch = buf[i];
if (ch == '\b' || ch == '\n' || ch == '\r' || ch == '\f' || ch == '\\'
|| ch == '\'' //
|| (ch == '\t' && isEnabled(SerializerFeature.WriteTabAsSpecial))
if (ch <= 13 || ch == '\\' || ch == '\'' //
|| (ch == '/' && isEnabled(SerializerFeature.WriteSlashAsSpecial))) {
System.arraycopy(buf, i + 1, buf, i + 2, end - i - 1);
buf[i] = '\\';
@@ -1364,7 +1351,7 @@ public final class SerializeWriter extends Writer {
break;
}
}
if (hasSpecial) {
write('"');
}
@@ -1446,7 +1433,7 @@ public final class SerializeWriter extends Writer {
break;
}
}
if (hasSpecial) {
write('"');
}
@@ -1465,7 +1452,7 @@ public final class SerializeWriter extends Writer {
write(':');
return;
}
expandCapacity(newcount);
}
@@ -64,6 +64,7 @@ public enum SerializerFeature {
/**
* @since 1.1.1
*/
@Deprecated
WriteTabAsSpecial,
/**
* @since 1.1.2
@@ -1,8 +1,9 @@
package com.alibaba.json.bvt;
import junit.framework.Assert;
import junit.framework.TestCase;
import org.junit.Assert;
import com.alibaba.fastjson.parser.CharTypes;
public class CharTypesTest extends TestCase {
@@ -14,7 +15,7 @@ public class CharTypesTest extends TestCase {
Assert.assertTrue(CharTypes.isSpecial_doubleQuotes('\f'));
Assert.assertTrue(CharTypes.isSpecial_doubleQuotes('\"'));
Assert.assertFalse(CharTypes.isSpecial_doubleQuotes('0'));
Assert.assertFalse(CharTypes.isSpecial_doubleQuotes('\0'));
Assert.assertTrue(CharTypes.isSpecial_doubleQuotes('\0'));
Assert.assertFalse(CharTypes.isSpecial_doubleQuotes('中'));
Assert.assertFalse(CharTypes.isSpecial_doubleQuotes('中'));
}
@@ -1,8 +1,9 @@
package com.alibaba.json.bvt;
import junit.framework.Assert;
import junit.framework.TestCase;
import org.junit.Assert;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializeConfig;
@@ -10,11 +11,12 @@ import com.alibaba.fastjson.serializer.SerializerFeature;
public class TabCharTest extends TestCase {
@SuppressWarnings("deprecation")
public void test_0() throws Exception {
JSONObject json = new JSONObject();
json.put("hello\t", "World\t!");
Assert.assertEquals("{\"hello\\t\":\"World\\t!\"}", JSON.toJSONString(json));
Assert.assertEquals("{hello\t:\"World\t!\"}", JSON.toJSONStringZ(json, SerializeConfig.getGlobalInstance()));
Assert.assertEquals("{\"hello\\t\":\"World\\t!\"}", JSON.toJSONStringZ(json, SerializeConfig.getGlobalInstance()));
Assert.assertEquals("{'hello\\t':'World\\t!'}", JSON.toJSONString(json, SerializerFeature.WriteTabAsSpecial, SerializerFeature.UseSingleQuotes));
}
@@ -1,8 +1,9 @@
package com.alibaba.json.bvt.bug;
import junit.framework.Assert;
import junit.framework.TestCase;
import org.junit.Assert;
import com.alibaba.fastjson.JSON;
public class Bug_for_huling extends TestCase {
@@ -15,7 +16,7 @@ public class Bug_for_huling extends TestCase {
String text = JSON.toJSONString(vo);
System.out.println(text);
Assert.assertEquals("{\"value\":\"\0\0\"}", text);
Assert.assertEquals("{\"value\":\"\\0\\0\"}", text);
VO vo2 = JSON.parseObject(text, VO.class);
Assert.assertEquals("\0\0", vo2.getValue());
@@ -1,11 +1,13 @@
package com.alibaba.json.bvt.serializer;
import junit.framework.Assert;
import junit.framework.TestCase;
import org.junit.Assert;
import com.alibaba.fastjson.serializer.SerializeWriter;
import com.alibaba.fastjson.serializer.SerializerFeature;
@SuppressWarnings("deprecation")
public class SerializeWriterTest_2 extends TestCase {
public void test_0() throws Exception {
@@ -13,13 +15,15 @@ public class SerializeWriterTest_2 extends TestCase {
out.config(SerializerFeature.WriteTabAsSpecial, true);
out.writeString("\t\n \b\n\r\f\\ \"");
Assert.assertEquals("\"\\t\\n \\b\\n\\r\\f\\\\ \\\"\"", out.toString());
out.close();
}
public void test_1() throws Exception {
SerializeWriter out = new SerializeWriter(1);
out.config(SerializerFeature.WriteTabAsSpecial, true);
out.config(SerializerFeature.UseSingleQuotes, true);
out.writeString("\t\n \b\n\r\f\\ \"");
Assert.assertEquals("'\\t\\n \\b\\n\\r\\f\\\\ \"'", out.toString());
out.close();
}
}
@@ -1,11 +1,13 @@
package com.alibaba.json.bvt.serializer;
import junit.framework.Assert;
import junit.framework.TestCase;
import org.junit.Assert;
import com.alibaba.fastjson.serializer.SerializeWriter;
import com.alibaba.fastjson.serializer.SerializerFeature;
@SuppressWarnings("deprecation")
public class SerializeWriterTest_4 extends TestCase {
public void test_0() throws Exception {
@@ -14,6 +16,7 @@ public class SerializeWriterTest_4 extends TestCase {
out.config(SerializerFeature.WriteTabAsSpecial, true);
out.writeFieldValue(',', "name", "\t");
Assert.assertEquals(",\"name\":\"\\t\"", out.toString());
out.close();
}
public void test_1() throws Exception {
@@ -22,6 +25,7 @@ public class SerializeWriterTest_4 extends TestCase {
out.config(SerializerFeature.WriteTabAsSpecial, true);
out.writeFieldValue(',', "name", "\t\n");
Assert.assertEquals(",\"name\":\"\\t\\n\"", out.toString());
out.close();
}
public void test_3() throws Exception {
@@ -30,6 +34,7 @@ public class SerializeWriterTest_4 extends TestCase {
out.config(SerializerFeature.WriteTabAsSpecial, true);
out.writeFieldValue(',', "name", "\t\n \b\n\r\f\\ \"");
Assert.assertEquals(",\"name\":\"\\t\\n \\b\\n\\r\\f\\\\ \\\"\"", out.toString());
out.close();
}
public void test_4() throws Exception {
@@ -37,7 +42,8 @@ public class SerializeWriterTest_4 extends TestCase {
out.config(SerializerFeature.QuoteFieldNames, true);
out.config(SerializerFeature.WriteTabAsSpecial, false);
out.writeFieldValue(',', "name", "\t\n \b\n\r\f\\ \"");
Assert.assertEquals(",\"name\":\"\t\\n \\b\\n\\r\\f\\\\ \\\"\"", out.toString());
Assert.assertEquals(",\"name\":\"\\t\\n \\b\\n\\r\\f\\\\ \\\"\"", out.toString());
out.close();
}
public void test_5() throws Exception {
@@ -46,5 +52,6 @@ public class SerializeWriterTest_4 extends TestCase {
out.config(SerializerFeature.WriteTabAsSpecial, true);
out.writeString("\t\n \b\n\r\f\\ \"");
Assert.assertEquals("\"\\t\\n \\b\\n\\r\\f\\\\ \\\"\"", out.toString());
out.close();
}
}
@@ -9,6 +9,7 @@ import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
public class TestSpecial extends TestCase {
@SuppressWarnings("deprecation")
public void test_0 () throws Exception {
Map<String, Object> map = new HashMap<String, Object>();
map.put("name", "\n\r\t");
@@ -0,0 +1,56 @@
package com.alibaba.json.bvt.serializer;
import junit.framework.TestCase;
import org.junit.Assert;
import com.alibaba.fastjson.JSON;
public class TestSpecial_entity extends TestCase {
public void test_0() throws Exception {
Assert.assertEquals("{\"name\":\"\\0\"}", JSON.toJSONString(new VO("\0")));
}
public void test_1() throws Exception {
Assert.assertEquals("{\"name\":\"\\1\"}", JSON.toJSONString(new VO("\1")));
}
public void test_2() throws Exception {
Assert.assertEquals("{\"name\":\"\\2\"}", JSON.toJSONString(new VO("\2")));
}
public void test_3() throws Exception {
Assert.assertEquals("{\"name\":\"\\3\"}", JSON.toJSONString(new VO("\3")));
}
public void test_4() throws Exception {
Assert.assertEquals("{\"name\":\"\\4\"}", JSON.toJSONString(new VO("\4")));
}
public void test_5() throws Exception {
Assert.assertEquals("{\"name\":\"\\5\"}", JSON.toJSONString(new VO("\5")));
}
public static class VO {
private String name;
public VO(){
}
public VO(String name){
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}
@@ -0,0 +1,48 @@
package com.alibaba.json.bvt.serializer;
import java.util.Collections;
import junit.framework.TestCase;
import org.junit.Assert;
import com.alibaba.fastjson.JSON;
public class TestSpecial_map extends TestCase {
public void test_0() throws Exception {
Assert.assertEquals("{\"name\":\"\\0\"}", JSON.toJSONString(Collections.singletonMap("name", "\0")));
}
public void test_1() throws Exception {
Assert.assertEquals("{\"name\":\"\\1\"}", JSON.toJSONString(Collections.singletonMap("name", "\1")));
}
public void test_2() throws Exception {
Assert.assertEquals("{\"name\":\"\\2\"}", JSON.toJSONString(Collections.singletonMap("name", "\2")));
}
public void test_3() throws Exception {
Assert.assertEquals("{\"name\":\"\\3\"}", JSON.toJSONString(Collections.singletonMap("name", "\3")));
}
public void test_4() throws Exception {
Assert.assertEquals("{\"name\":\"\\4\"}", JSON.toJSONString(Collections.singletonMap("name", "\4")));
}
public void test_5() throws Exception {
Assert.assertEquals("{\"name\":\"\\5\"}", JSON.toJSONString(Collections.singletonMap("name", "\5")));
}
public void test_6() throws Exception {
Assert.assertEquals("{\"name\":\"\\6\"}", JSON.toJSONString(Collections.singletonMap("name", "\6")));
}
public void test_7() throws Exception {
Assert.assertEquals("{\"name\":\"\\7\"}", JSON.toJSONString(Collections.singletonMap("name", "\7")));
}
public void test_8() throws Exception {
Assert.assertEquals("{\"name\":\"\\b\"}", JSON.toJSONString(Collections.singletonMap("name", "\b")));
}
}
@@ -1,11 +1,13 @@
package com.alibaba.json.test;
import junit.framework.Assert;
import junit.framework.TestCase;
import org.junit.Assert;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
@SuppressWarnings("deprecation")
public class TestWriteSlashAsSpecial extends TestCase {
private int defaultValue = JSON.DEFAULT_GENERATE_FEATURE;