From 0d05c96c718cbb1ec9131e227910381d2a6502c1 Mon Sep 17 00:00:00 2001 From: mozhu Date: Mon, 4 May 2015 17:48:58 +0800 Subject: [PATCH 1/7] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=E7=89=B9=E5=AE=9A?= =?UTF-8?q?=E6=83=85=E5=86=B5=E4=B8=8B=EF=BC=8C=E5=BD=93=20127>> 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; } } From b0ce3c874e5a1f43fe4ea77809d76bcbaf6d524d Mon Sep 17 00:00:00 2001 From: CodePlayer Date: Tue, 5 May 2015 17:23:37 +0800 Subject: [PATCH 2/7] add includes support in JSONType --- .../alibaba/fastjson/annotation/JSONType.java | 4 +++- .../com/alibaba/fastjson/util/TypeUtils.java | 22 +++++++++++++++---- 2 files changed, 21 insertions(+), 5 deletions(-) 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/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; + } } } } From 1352a7365844366f7444409d0875c1cab0c37ab5 Mon Sep 17 00:00:00 2001 From: mozhu Date: Wed, 6 May 2015 20:27:52 +0800 Subject: [PATCH 3/7] =?UTF-8?q?=E6=B7=BB=E5=8A=A0SerializeWriter=E7=9A=84T?= =?UTF-8?q?estcase?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../serializer/SerializeWriterTest.java | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 src/test/java/com/alibaba/fastjson/serializer/SerializeWriterTest.java 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..a53591995 --- /dev/null +++ b/src/test/java/com/alibaba/fastjson/serializer/SerializeWriterTest.java @@ -0,0 +1,85 @@ +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 { + // make special chars + + this.doTestWrite(this.makeSpecialChars()); + } + + private String makeSpecialChars() { + StringBuilder strBuilder = new StringBuilder(128); + for (char c = 127; 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()); + } +} From 9424aa1761dc298c4771e082700df89ea98ce845 Mon Sep 17 00:00:00 2001 From: mozhu Date: Wed, 6 May 2015 20:43:24 +0800 Subject: [PATCH 4/7] =?UTF-8?q?=E4=BF=AE=E6=AD=A3test=20case=20=E4=B8=AD?= =?UTF-8?q?=E7=89=B9=E6=AE=8A=E5=AD=97=E7=AC=A6=E8=8C=83=E5=9B=B4=E6=9C=89?= =?UTF-8?q?=E8=AF=AF=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/alibaba/fastjson/serializer/SerializeWriterTest.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/test/java/com/alibaba/fastjson/serializer/SerializeWriterTest.java b/src/test/java/com/alibaba/fastjson/serializer/SerializeWriterTest.java index a53591995..05fe40334 100644 --- a/src/test/java/com/alibaba/fastjson/serializer/SerializeWriterTest.java +++ b/src/test/java/com/alibaba/fastjson/serializer/SerializeWriterTest.java @@ -49,14 +49,12 @@ public class SerializeWriterTest { @Test public void testWriteLiteSpecilaStr() throws UnsupportedEncodingException { - // make special chars - this.doTestWrite(this.makeSpecialChars()); } private String makeSpecialChars() { StringBuilder strBuilder = new StringBuilder(128); - for (char c = 127; c < 160; c++) { + for (char c = 128; c <= 160; c++) { strBuilder.append(c); } return strBuilder.toString(); From 7aab41e043baaa39507fbcf8149d28f10452a584 Mon Sep 17 00:00:00 2001 From: Jerry Lee Date: Sun, 10 May 2015 21:44:36 +0800 Subject: [PATCH 5/7] add badges in read me #334 --- README.md | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index a82fded8a..31e421816 100755 --- a/README.md +++ b/README.md @@ -1,25 +1,32 @@ # fastjson +[![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.alibaba/fastjson/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.alibaba/fastjson/) +[![GitHub release](https://img.shields.io/github/release/alibaba/fastjson.svg)](https://github.com/alibaba/fastjson/releases) +[![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg)](https://www.apache.org/licenses/LICENSE-2.0.html) + Fast JSON Processor -![](logo.jpg) +![fastjson](logo.jpg "fastjson") ## 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 + +``` From 52df4fa0f12436b7a9b4a8de0e4a81e0cad949dd Mon Sep 17 00:00:00 2001 From: Yako Date: Thu, 21 May 2015 17:01:43 +0800 Subject: [PATCH 6/7] supoort SerializerFeature.BrowserSecure --- .../fastjson/serializer/MapSerializer.java | 3 +- .../fastjson/serializer/SerializeWriter.java | 66 +++++++++++++- .../serializer/SerializerFeature.java | 7 +- .../SerializeWriterTest_BrowserSecure.java | 87 +++++++++++++++++++ .../bvt/serializer/SerializerFeatureTest.java | 8 ++ 5 files changed, 166 insertions(+), 5 deletions(-) create mode 100644 src/test/java/com/alibaba/json/bvt/serializer/SerializeWriterTest_BrowserSecure.java 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 0eab130cb..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' // @@ -689,7 +700,7 @@ public final class SerializeWriter extends Writer { } else { write(IOUtils.replaceChars[ch]); } - continue; + continue; } } @@ -713,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; @@ -1200,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/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