diff --git a/README.md b/README.md
index a82fded8a..31e421816 100755
--- a/README.md
+++ b/README.md
@@ -1,25 +1,32 @@
# fastjson
+[](https://maven-badges.herokuapp.com/maven-central/com.alibaba/fastjson/)
+[](https://github.com/alibaba/fastjson/releases)
+[](https://www.apache.org/licenses/LICENSE-2.0.html)
+
Fast JSON Processor
-
+
## Documentation
-https://github.com/alibaba/fastjson/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98
+
+- [Documentation Home](https://github.com/alibaba/fastjson/wiki)
+- [Frequently Asked Questions](https://github.com/alibaba/fastjson/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98)
## Benchmark
+
https://github.com/eishay/jvm-serializers/wiki
-
## Download
-http://repo1.maven.org/maven2/com/alibaba/fastjson/
+http://repo1.maven.org/maven2/com/alibaba/fastjson/
## Maven
-
- com.alibaba
- fastjson
- x.x.x
-
-
+```xml
+
+ com.alibaba
+ fastjson
+ x.x.x
+
+```
diff --git a/pom.xml b/pom.xml
index d8c1831d7..2413cf03e 100755
--- a/pom.xml
+++ b/pom.xml
@@ -12,7 +12,7 @@
com.alibaba
fastjson
- 1.2.5
+ 1.2.6
jar
fastjson
diff --git a/src/main/java/com/alibaba/fastjson/JSON.java b/src/main/java/com/alibaba/fastjson/JSON.java
index a46a8b3ee..7a57edb0d 100755
--- a/src/main/java/com/alibaba/fastjson/JSON.java
+++ b/src/main/java/com/alibaba/fastjson/JSON.java
@@ -737,5 +737,5 @@ public abstract class JSON implements JSONStreamAware, JSONAware {
}
}
- public final static String VERSION = "1.2.5";
+ public final static String VERSION = "1.2.6";
}
diff --git a/src/main/java/com/alibaba/fastjson/annotation/JSONType.java b/src/main/java/com/alibaba/fastjson/annotation/JSONType.java
index 6d0374072..f5ddd5d57 100755
--- a/src/main/java/com/alibaba/fastjson/annotation/JSONType.java
+++ b/src/main/java/com/alibaba/fastjson/annotation/JSONType.java
@@ -18,7 +18,9 @@ public @interface JSONType {
boolean asm() default true;
String[] orders() default {};
-
+
+ String[] includes() default {};
+
String[] ignores() default {};
SerializerFeature[] serialzeFeatures() default {};
diff --git a/src/main/java/com/alibaba/fastjson/serializer/MapSerializer.java b/src/main/java/com/alibaba/fastjson/serializer/MapSerializer.java
index e2b7b5555..681d6d004 100755
--- a/src/main/java/com/alibaba/fastjson/serializer/MapSerializer.java
+++ b/src/main/java/com/alibaba/fastjson/serializer/MapSerializer.java
@@ -160,7 +160,8 @@ public class MapSerializer implements ObjectSerializer {
}
if (out.isEnabled(SerializerFeature.BrowserCompatible)
- || out.isEnabled(SerializerFeature.WriteNonStringKeyAsString)) {
+ || out.isEnabled(SerializerFeature.WriteNonStringKeyAsString)
+ || out.isEnabled(SerializerFeature.BrowserSecure)) {
String strEntryKey = JSON.toJSONString(entryKey);
serializer.write(strEntryKey);
} else {
diff --git a/src/main/java/com/alibaba/fastjson/serializer/SerializeWriter.java b/src/main/java/com/alibaba/fastjson/serializer/SerializeWriter.java
index 7955660e0..080162bd8 100755
--- a/src/main/java/com/alibaba/fastjson/serializer/SerializeWriter.java
+++ b/src/main/java/com/alibaba/fastjson/serializer/SerializeWriter.java
@@ -642,7 +642,18 @@ public final class SerializeWriter extends Writer {
for (int i = 0; i < text.length(); ++i) {
char ch = text.charAt(i);
- if (isEnabled(SerializerFeature.BrowserCompatible)) {
+ if (isEnabled(SerializerFeature.BrowserSecure)) {
+ if (!(ch >= '0' && ch <= '9') && !(ch >= 'a' && ch <= 'z') && !(ch >= 'A' && ch <= 'Z')
+ && !(ch == ',') && !(ch == '.') && !(ch == '_')) {
+ write('\\');
+ write('u');
+ write(IOUtils.DIGITS[(ch >>> 12) & 15]);
+ write(IOUtils.DIGITS[(ch >>> 8) & 15]);
+ write(IOUtils.DIGITS[(ch >>> 4) & 15]);
+ write(IOUtils.DIGITS[ch & 15]);
+ continue;
+ }
+ } else if (isEnabled(SerializerFeature.BrowserCompatible)) {
if (ch == '\b' //
|| ch == '\f' //
|| ch == '\n' //
@@ -680,7 +691,15 @@ public final class SerializeWriter extends Writer {
&& IOUtils.specicalFlags_doubleQuotes[ch] != 0 //
|| (ch == '/' && isEnabled(SerializerFeature.WriteSlashAsSpecial))) {
write('\\');
- write(replaceChars[(int) ch]);
+ if (IOUtils.specicalFlags_doubleQuotes[ch] == 4) {
+ write('u');
+ write(IOUtils.DIGITS[ch >>> 12 & 15]);
+ write(IOUtils.DIGITS[ch >>> 8 & 15]);
+ write(IOUtils.DIGITS[ch >>> 4 & 15]);
+ write(IOUtils.DIGITS[ch & 15]);
+ } else {
+ write(IOUtils.replaceChars[ch]);
+ }
continue;
}
}
@@ -705,6 +724,51 @@ public final class SerializeWriter extends Writer {
count = newcount;
+ if (isEnabled(SerializerFeature.BrowserSecure)) {
+ int lastSpecialIndex = -1;
+
+ for (int i = start; i < end; ++i) {
+ char ch = buf[i];
+
+ if (!(ch >= '0' && ch <= '9') && !(ch >= 'a' && ch <= 'z') && !(ch >= 'A' && ch <= 'Z')
+ && !(ch == ',') && !(ch == '.') && !(ch == '_')) {
+ lastSpecialIndex = i;
+ newcount += 5;
+ continue;
+ }
+ }
+
+ if (newcount > buf.length) {
+ expandCapacity(newcount);
+ }
+ count = newcount;
+
+ for (int i = lastSpecialIndex; i >= start; --i) {
+ char ch = buf[i];
+
+ if (!(ch >= '0' && ch <= '9') && !(ch >= 'a' && ch <= 'z') && !(ch >= 'A' && ch <= 'Z') && !(ch == ',')
+ && !(ch == '.') && !(ch == '_')) {
+ System.arraycopy(buf, i + 1, buf, i + 6, end - i - 1);
+ buf[i] = '\\';
+ buf[i + 1] = 'u';
+ buf[i + 2] = IOUtils.DIGITS[(ch >>> 12) & 15];
+ buf[i + 3] = IOUtils.DIGITS[(ch >>> 8) & 15];
+ buf[i + 4] = IOUtils.DIGITS[(ch >>> 4) & 15];
+ buf[i + 5] = IOUtils.DIGITS[ch & 15];
+ end += 5;
+ }
+ }
+
+ if (seperator != 0) {
+ buf[count - 2] = '\"';
+ buf[count - 1] = seperator;
+ } else {
+ buf[count - 1] = '\"';
+ }
+
+ return;
+ }
+
if (isEnabled(SerializerFeature.BrowserCompatible)) {
int lastSpecialIndex = -1;
@@ -1192,7 +1256,11 @@ public final class SerializeWriter extends Writer {
writeString(value);
}
} else {
- if (isEnabled(SerializerFeature.BrowserCompatible)) {
+ if (isEnabled(SerializerFeature.BrowserSecure)) {
+ write(seperator);
+ writeStringWithDoubleQuote(name, ':');
+ writeStringWithDoubleQuote(value, (char) 0);
+ } else if (isEnabled(SerializerFeature.BrowserCompatible)) {
write(seperator);
writeStringWithDoubleQuote(name, ':');
writeStringWithDoubleQuote(value, (char) 0);
diff --git a/src/main/java/com/alibaba/fastjson/serializer/SerializerFeature.java b/src/main/java/com/alibaba/fastjson/serializer/SerializerFeature.java
index dd5d67969..03bcf0b1b 100755
--- a/src/main/java/com/alibaba/fastjson/serializer/SerializerFeature.java
+++ b/src/main/java/com/alibaba/fastjson/serializer/SerializerFeature.java
@@ -121,7 +121,12 @@ public enum SerializerFeature {
/**
* @since 1.1.42
*/
- NotWriteDefaultValue
+ NotWriteDefaultValue,
+
+ /**
+ * @since 1.2.6
+ */
+ BrowserSecure,
;
private SerializerFeature(){
diff --git a/src/main/java/com/alibaba/fastjson/util/TypeUtils.java b/src/main/java/com/alibaba/fastjson/util/TypeUtils.java
index 0900749b0..bf1d9fdb6 100755
--- a/src/main/java/com/alibaba/fastjson/util/TypeUtils.java
+++ b/src/main/java/com/alibaba/fastjson/util/TypeUtils.java
@@ -1267,10 +1267,24 @@ public class TypeUtils {
private static boolean isJSONTypeIgnore(Class> clazz, String propertyName) {
JSONType jsonType = clazz.getAnnotation(JSONType.class);
- if (jsonType != null && jsonType.ignores() != null) {
- for (String item : jsonType.ignores()) {
- if (propertyName.equalsIgnoreCase(item)) {
- return true;
+ if (jsonType != null) {
+ // 1、新增 includes 支持,如果 JSONType 同时设置了includes 和 ignores 属性,则以includes为准。
+ // 2、个人认为对于大小写敏感的Java和JS而言,使用 equals() 比 equalsIgnoreCase() 更好,改动的唯一风险就是向后兼容性的问题
+ // 不过,相信开发者应该都是严格按照大小写敏感的方式进行属性设置的
+ String[] fields = jsonType.includes();
+ if (fields.length > 0) {
+ for (int i = 0; i < fields.length; i++) {
+ if (propertyName.equals(fields[i])) {
+ return false;
+ }
+ }
+ return true;
+ } else {
+ fields = jsonType.ignores();
+ for (int i = 0; i < fields.length; i++) {
+ if (propertyName.equals(fields[i])) {
+ return true;
+ }
}
}
}
diff --git a/src/test/java/com/alibaba/fastjson/serializer/SerializeWriterTest.java b/src/test/java/com/alibaba/fastjson/serializer/SerializeWriterTest.java
new file mode 100644
index 000000000..05fe40334
--- /dev/null
+++ b/src/test/java/com/alibaba/fastjson/serializer/SerializeWriterTest.java
@@ -0,0 +1,83 @@
+package com.alibaba.fastjson.serializer;
+
+import java.io.ByteArrayOutputStream;
+import java.io.OutputStreamWriter;
+import java.io.UnsupportedEncodingException;
+import java.util.logging.Logger;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.util.IOUtils;
+
+public class SerializeWriterTest {
+
+ private final Logger logger = Logger.getLogger(SerializeWriterTest.class.getSimpleName());
+
+ private final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+ private final SerializeWriter writer = new SerializeWriter(new OutputStreamWriter(baos));
+
+ @Before
+ public void setUp() throws Exception {
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ }
+
+ @Test
+ public void testWriteLiteBasicStr() throws UnsupportedEncodingException {
+ String targetStr = new String(IOUtils.DIGITS);
+ this.doTestWrite(targetStr);
+ }
+
+ private String doTestWrite(String input) throws UnsupportedEncodingException {
+ writer.writeString(input, (char) 0);
+ writer.flush();
+ String result = this.baos.toString("UTF-8");
+
+ Assert.assertEquals(input, JSON.parse(result));
+
+ logger.info(result);
+
+ return result;
+ }
+
+ @Test
+ public void testWriteLiteSpecilaStr() throws UnsupportedEncodingException {
+ this.doTestWrite(this.makeSpecialChars());
+ }
+
+ private String makeSpecialChars() {
+ StringBuilder strBuilder = new StringBuilder(128);
+ for (char c = 128; c <= 160; c++) {
+ strBuilder.append(c);
+ }
+ return strBuilder.toString();
+ }
+
+ @Test
+ public void testWriteLargeBasicStr() throws UnsupportedEncodingException {
+ String tmp = new String(IOUtils.DIGITS);
+ StringBuilder builder = new StringBuilder();
+ for (int i = 0; i < 200; i++) {
+ builder.append(tmp);
+ }
+ this.doTestWrite(builder.toString());
+ }
+
+ @Test
+ public void testWriteLargeSpecialStr() throws UnsupportedEncodingException {
+
+ String tmp = this.makeSpecialChars();
+ StringBuilder builder = new StringBuilder();
+ for (int i = 0; i < 200; i++) {
+ builder.append(tmp);
+ }
+ this.doTestWrite(builder.toString());
+ }
+}
diff --git a/src/test/java/com/alibaba/json/bvt/serializer/SerializeWriterTest_BrowserSecure.java b/src/test/java/com/alibaba/json/bvt/serializer/SerializeWriterTest_BrowserSecure.java
new file mode 100644
index 000000000..fb56d297a
--- /dev/null
+++ b/src/test/java/com/alibaba/json/bvt/serializer/SerializeWriterTest_BrowserSecure.java
@@ -0,0 +1,87 @@
+package com.alibaba.json.bvt.serializer;
+
+import java.io.StringWriter;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Assert;
+
+import junit.framework.TestCase;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.serializer.SerializerFeature;
+
+public class SerializeWriterTest_BrowserSecure extends TestCase {
+
+ public void test_0() throws Exception {
+ StringBuilder buf = new StringBuilder();
+ for (int i = 0; i < 1024; ++i) {
+ buf.append('a');
+ }
+ buf.append("中国");
+ buf.append("\0");
+ JSON.toJSONString(buf.toString(), SerializerFeature.BrowserSecure);
+ }
+
+ public void test_1() throws Exception {
+ StringBuilder buf = new StringBuilder();
+ for (int i = 0; i < 1024; ++i) {
+ buf.append('a');
+ }
+ buf.append("中国");
+ buf.append("\0");
+
+ StringWriter out = new StringWriter();
+ JSON.writeJSONStringTo(buf.toString(), out, SerializerFeature.BrowserSecure);
+ }
+
+ public void test_zh() throws Exception {
+ Assert.assertEquals("\"\\u4E2D\\u56FD\"", JSON.toJSONString("中国", SerializerFeature.BrowserSecure));
+ }
+
+ public void test_all() throws Exception {
+ String value = ".,_~!@<>'\"\\/hello world 0123;汉字;\u2028\u2028\r\n