diff --git a/src/main/java/com/alibaba/fastjson/serializer/SerializeWriter.java b/src/main/java/com/alibaba/fastjson/serializer/SerializeWriter.java index f0dece1411..739f4b1b93 100755 --- a/src/main/java/com/alibaba/fastjson/serializer/SerializeWriter.java +++ b/src/main/java/com/alibaba/fastjson/serializer/SerializeWriter.java @@ -795,80 +795,129 @@ private void writeStringWithDoubleQuote(String text, final char seperator, boole if (checkSpecial) { for (int i = start; i < end; ++i) { char ch = buf[i]; + + if (ch == '\u2028') { + specialCount++; + lastSpecialIndex = i; + lastSpecial = ch; + newcount += 4; + + if (firstSpecialIndex == -1) { + firstSpecialIndex = i; + } + continue; + } + if (ch >= ']') { - if (ch == '\u2028') { + if (ch >= 0x7F && ch <= 0xA0) { + if (firstSpecialIndex == -1) { + firstSpecialIndex = i; + } + specialCount++; lastSpecialIndex = i; lastSpecial = ch; newcount += 4; - if (firstSpecialIndex == -1) { - firstSpecialIndex = i; - } } continue; } - if (ch == ' ') { - continue; - } - - if (ch >= '0' && ch != '\\') { - continue; - } - - if (ch < CharTypes.specicalFlags_doubleQuotes.length && CharTypes.specicalFlags_doubleQuotes[ch] != 0 // - || (ch == '/' && isEnabled(SerializerFeature.WriteSlashAsSpecial))) { + if (isSpecial(ch, this.features)) { specialCount++; lastSpecialIndex = i; lastSpecial = ch; + if (ch < CharTypes.specicalFlags_doubleQuotes.length // + && CharTypes.specicalFlags_doubleQuotes[ch] == 4 // + ) { + newcount += 4; + } + if (firstSpecialIndex == -1) { firstSpecialIndex = i; } } } - } - newcount += specialCount; - if (newcount > buf.length) { - expandCapacity(newcount); - } - count = newcount; + if (specialCount > 0) { + newcount += specialCount; + if (newcount > buf.length) { + expandCapacity(newcount); + } + count = newcount; - if (specialCount == 1) { - if (lastSpecial == '\u2028') { - int srcPos = lastSpecialIndex + 1; - int destPos = lastSpecialIndex + 6; - int LengthOfCopy = end - lastSpecialIndex - 1; - System.arraycopy(buf, srcPos, buf, destPos, LengthOfCopy); - buf[lastSpecialIndex] = '\\'; - buf[++lastSpecialIndex] = 'u'; - buf[++lastSpecialIndex] = '2'; - buf[++lastSpecialIndex] = '0'; - buf[++lastSpecialIndex] = '2'; - buf[++lastSpecialIndex] = '8'; - } else { - int srcPos = lastSpecialIndex + 1; - int destPos = lastSpecialIndex + 2; - int LengthOfCopy = end - lastSpecialIndex - 1; - System.arraycopy(buf, srcPos, buf, destPos, LengthOfCopy); - buf[lastSpecialIndex] = '\\'; - buf[++lastSpecialIndex] = replaceChars[(int) lastSpecial]; - } - } else if (specialCount > 1) { - int textIndex = firstSpecialIndex - start; - int bufIndex = firstSpecialIndex; - for (int i = textIndex; i < text.length(); ++i) { - char ch = text.charAt(i); + if (specialCount == 1) { + if (lastSpecial == '\u2028') { + int srcPos = lastSpecialIndex + 1; + int destPos = lastSpecialIndex + 6; + int LengthOfCopy = end - lastSpecialIndex - 1; + System.arraycopy(buf, srcPos, buf, destPos, LengthOfCopy); + buf[lastSpecialIndex] = '\\'; + buf[++lastSpecialIndex] = 'u'; + buf[++lastSpecialIndex] = '2'; + buf[++lastSpecialIndex] = '0'; + buf[++lastSpecialIndex] = '2'; + buf[++lastSpecialIndex] = '8'; + } else { + final char ch = lastSpecial; + if (ch < CharTypes.specicalFlags_doubleQuotes.length // + && CharTypes.specicalFlags_doubleQuotes[ch] == 4) { + int srcPos = lastSpecialIndex + 1; + int destPos = lastSpecialIndex + 6; + int LengthOfCopy = end - lastSpecialIndex - 1; + System.arraycopy(buf, srcPos, buf, destPos, LengthOfCopy); - if (ch < CharTypes.specicalFlags_doubleQuotes.length // - && CharTypes.specicalFlags_doubleQuotes[ch] != 0 // - || (ch == '/' && isEnabled(SerializerFeature.WriteSlashAsSpecial))) { - buf[bufIndex++] = '\\'; - buf[bufIndex++] = replaceChars[(int) ch]; - end++; - } else { - buf[bufIndex++] = ch; + int bufIndex = lastSpecialIndex; + buf[bufIndex++] = '\\'; + buf[bufIndex++] = 'u'; + buf[bufIndex++] = CharTypes.digits[(ch >>> 12) & 15]; + buf[bufIndex++] = CharTypes.digits[(ch >>> 8) & 15]; + buf[bufIndex++] = CharTypes.digits[(ch >>> 4) & 15]; + buf[bufIndex++] = CharTypes.digits[ch & 15]; + } else { + int srcPos = lastSpecialIndex + 1; + int destPos = lastSpecialIndex + 2; + int LengthOfCopy = end - lastSpecialIndex - 1; + System.arraycopy(buf, srcPos, buf, destPos, LengthOfCopy); + buf[lastSpecialIndex] = '\\'; + buf[++lastSpecialIndex] = replaceChars[(int) ch]; + } + } + } else if (specialCount > 1) { + int textIndex = firstSpecialIndex - start; + int bufIndex = firstSpecialIndex; + for (int i = textIndex; i < text.length(); ++i) { + char ch = text.charAt(i); + + if (ch < CharTypes.specicalFlags_doubleQuotes.length // + && CharTypes.specicalFlags_doubleQuotes[ch] != 0 // + || (ch == '/' && isEnabled(SerializerFeature.WriteSlashAsSpecial))) { + buf[bufIndex++] = '\\'; + if (CharTypes.specicalFlags_doubleQuotes[ch] == 4) { + buf[bufIndex++] = 'u'; + buf[bufIndex++] = CharTypes.digits[(ch >>> 12) & 15]; + buf[bufIndex++] = CharTypes.digits[(ch >>> 8) & 15]; + buf[bufIndex++] = CharTypes.digits[(ch >>> 4) & 15]; + buf[bufIndex++] = CharTypes.digits[ch & 15]; + end += 5; + } else { + buf[bufIndex++] = replaceChars[(int) ch]; + end++; + } + } else { + if (ch == '\u2028') { + buf[bufIndex++] = '\\'; + buf[bufIndex++] = 'u'; + buf[bufIndex++] = CharTypes.digits[(ch >>> 12) & 15]; + buf[bufIndex++] = CharTypes.digits[(ch >>> 8) & 15]; + buf[bufIndex++] = CharTypes.digits[(ch >>> 4) & 15]; + buf[bufIndex++] = CharTypes.digits[ch & 15]; + end += 5; + } else { + buf[bufIndex++] = ch; + } + } + } } } } @@ -1273,14 +1322,7 @@ private void writeFieldValueStringWithDoubleQuote(char seperator, String name, S } else { final char ch = lastSpecial; if (ch < CharTypes.specicalFlags_doubleQuotes.length // - && CharTypes.specicalFlags_doubleQuotes[ch] == 1) { - int srcPos = lastSpecialIndex + 1; - int destPos = lastSpecialIndex + 2; - int LengthOfCopy = valueEnd - lastSpecialIndex - 1; - System.arraycopy(buf, srcPos, buf, destPos, LengthOfCopy); - buf[lastSpecialIndex] = '\\'; - buf[++lastSpecialIndex] = replaceChars[(int) ch]; - } else { + && CharTypes.specicalFlags_doubleQuotes[ch] == 4) { int srcPos = lastSpecialIndex + 1; int destPos = lastSpecialIndex + 6; int LengthOfCopy = valueEnd - lastSpecialIndex - 1; @@ -1293,6 +1335,13 @@ private void writeFieldValueStringWithDoubleQuote(char seperator, String name, S buf[bufIndex++] = CharTypes.digits[(ch >>> 8) & 15]; buf[bufIndex++] = CharTypes.digits[(ch >>> 4) & 15]; buf[bufIndex++] = CharTypes.digits[ch & 15]; + } else { + int srcPos = lastSpecialIndex + 1; + int destPos = lastSpecialIndex + 2; + int LengthOfCopy = valueEnd - lastSpecialIndex - 1; + System.arraycopy(buf, srcPos, buf, destPos, LengthOfCopy); + buf[lastSpecialIndex] = '\\'; + buf[++lastSpecialIndex] = replaceChars[(int) ch]; } } } else if (specialCount > 1) { @@ -1305,16 +1354,16 @@ private void writeFieldValueStringWithDoubleQuote(char seperator, String name, S && CharTypes.specicalFlags_doubleQuotes[ch] != 0 // || (ch == '/' && isEnabled(SerializerFeature.WriteSlashAsSpecial))) { buf[bufIndex++] = '\\'; - if (CharTypes.specicalFlags_doubleQuotes[ch] == 1) { - buf[bufIndex++] = replaceChars[(int) ch]; - valueEnd++; - } else { + if (CharTypes.specicalFlags_doubleQuotes[ch] == 4) { buf[bufIndex++] = 'u'; buf[bufIndex++] = CharTypes.digits[(ch >>> 12) & 15]; buf[bufIndex++] = CharTypes.digits[(ch >>> 8) & 15]; buf[bufIndex++] = CharTypes.digits[(ch >>> 4) & 15]; buf[bufIndex++] = CharTypes.digits[ch & 15]; valueEnd += 5; + } else { + buf[bufIndex++] = replaceChars[(int) ch]; + valueEnd++; } } else { if (ch == '\u2028') { diff --git a/src/test/java/com/alibaba/json/bvt/bug/Bug_for_dongqi.java b/src/test/java/com/alibaba/json/bvt/bug/Bug_for_dongqi.java new file mode 100644 index 0000000000..16a09a628b --- /dev/null +++ b/src/test/java/com/alibaba/json/bvt/bug/Bug_for_dongqi.java @@ -0,0 +1,20 @@ +package com.alibaba.json.bvt.bug; + +import java.util.HashMap; +import java.util.Map; + +import org.junit.Assert; + +import junit.framework.TestCase; + +import com.alibaba.fastjson.JSON; + + +public class Bug_for_dongqi extends TestCase { + public void test_bug() throws Exception { + Map obj = new HashMap(); + obj.put("value", ";\r\n3、ž 公"); + System.out.print(JSON.toJSONString(obj)); + Assert.assertEquals("{\"value\":\";\\r\\n3、\\u009E 公\"}", JSON.toJSONString(obj)); + } +} diff --git a/src/test/java/com/alibaba/json/bvt/serializer/TestSpecial_map.java b/src/test/java/com/alibaba/json/bvt/serializer/TestSpecial_map.java index ed13fd9f78..1866b1c37c 100644 --- a/src/test/java/com/alibaba/json/bvt/serializer/TestSpecial_map.java +++ b/src/test/java/com/alibaba/json/bvt/serializer/TestSpecial_map.java @@ -11,35 +11,35 @@ public class TestSpecial_map extends TestCase { public void test_0() throws Exception { - Assert.assertEquals("{\"name\":\"\\0\"}", JSON.toJSONString(Collections.singletonMap("name", "\0"))); + Assert.assertEquals("{\"name\":\"\\u0000\"}", JSON.toJSONString(Collections.singletonMap("name", "\0"))); } public void test_1() throws Exception { - Assert.assertEquals("{\"name\":\"\\1\"}", JSON.toJSONString(Collections.singletonMap("name", "\1"))); + Assert.assertEquals("{\"name\":\"\\u0001\"}", JSON.toJSONString(Collections.singletonMap("name", "\1"))); } public void test_2() throws Exception { - Assert.assertEquals("{\"name\":\"\\2\"}", JSON.toJSONString(Collections.singletonMap("name", "\2"))); + Assert.assertEquals("{\"name\":\"\\u0002\"}", JSON.toJSONString(Collections.singletonMap("name", "\2"))); } public void test_3() throws Exception { - Assert.assertEquals("{\"name\":\"\\3\"}", JSON.toJSONString(Collections.singletonMap("name", "\3"))); + Assert.assertEquals("{\"name\":\"\\u0003\"}", JSON.toJSONString(Collections.singletonMap("name", "\3"))); } public void test_4() throws Exception { - Assert.assertEquals("{\"name\":\"\\4\"}", JSON.toJSONString(Collections.singletonMap("name", "\4"))); + Assert.assertEquals("{\"name\":\"\\u0004\"}", JSON.toJSONString(Collections.singletonMap("name", "\4"))); } public void test_5() throws Exception { - Assert.assertEquals("{\"name\":\"\\5\"}", JSON.toJSONString(Collections.singletonMap("name", "\5"))); + Assert.assertEquals("{\"name\":\"\\u0005\"}", JSON.toJSONString(Collections.singletonMap("name", "\5"))); } public void test_6() throws Exception { - Assert.assertEquals("{\"name\":\"\\6\"}", JSON.toJSONString(Collections.singletonMap("name", "\6"))); + Assert.assertEquals("{\"name\":\"\\u0006\"}", JSON.toJSONString(Collections.singletonMap("name", "\6"))); } public void test_7() throws Exception { - Assert.assertEquals("{\"name\":\"\\7\"}", JSON.toJSONString(Collections.singletonMap("name", "\7"))); + Assert.assertEquals("{\"name\":\"\\u0007\"}", JSON.toJSONString(Collections.singletonMap("name", "\7"))); } public void test_8() throws Exception {