Merge pull request #2 from alibaba/master

合并原作者更新
This commit is contained in:
shibenli
2015-05-27 10:40:02 +08:00
11 changed files with 297 additions and 22 deletions
+17 -10
View File
@@ -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
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>x.x.x</version>
</dependency>
```xml
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>x.x.x</version>
</dependency>
```
+1 -1
View File
@@ -12,7 +12,7 @@
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.5</version>
<version>1.2.6</version>
<packaging>jar</packaging>
<name>fastjson</name>
+1 -1
View File
@@ -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";
}
@@ -18,7 +18,9 @@ public @interface JSONType {
boolean asm() default true;
String[] orders() default {};
String[] includes() default {};
String[] ignores() default {};
SerializerFeature[] serialzeFeatures() default {};
@@ -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 {
@@ -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);
@@ -121,7 +121,12 @@ public enum SerializerFeature {
/**
* @since 1.1.42
*/
NotWriteDefaultValue
NotWriteDefaultValue,
/**
* @since 1.2.6
*/
BrowserSecure,
;
private SerializerFeature(){
@@ -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;
}
}
}
}
@@ -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());
}
}
@@ -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<script></scirpt>";
String expect = "\".,_\\u007E\\u0021\\u0040\\u003C\\u003E\\u0027\\u0022\\u005C\\u002Fhello\\u0020world\\u00200123\\u003B\\u6C49\\u5B57\\uFF1B\\u2028\\u2028\\u000D\\u000A\\u003Cscript\\u003E\\u003C\\u002Fscirpt\\u003E\"";
Assert.assertEquals(expect, JSON.toJSONString(value, SerializerFeature.BrowserSecure));
}
public void test_all_map() throws Exception {
String value = ".,_~!@<>'\"\\/hello world 0123;汉字;\u2028\u2028\r\n<script></scirpt>";
Map<String, String> map = new HashMap<String, String>();
map.put("value", value);
String expect = "{\"value\":\".,_\\u007E\\u0021\\u0040\\u003C\\u003E\\u0027\\u0022\\u005C\\u002Fhello\\u0020world\\u00200123\\u003B\\u6C49\\u5B57\\uFF1B\\u2028\\u2028\\u000D\\u000A\\u003Cscript\\u003E\\u003C\\u002Fscirpt\\u003E\"}";
String json = JSON.toJSONString(map, SerializerFeature.BrowserSecure);
Assert.assertEquals(expect, json);
Assert.assertEquals(value, JSON.parseObject(json).get("value"));
}
public void test_all_entity() throws Exception {
String value = ".,_~!@<>'\"\\/hello world 0123;汉字;\u2028\u2028\r\n<script></scirpt>";
VO vo = new VO();
vo.setValue(value);
String expect = "{\"value\":\".,_\\u007E\\u0021\\u0040\\u003C\\u003E\\u0027\\u0022\\u005C\\u002Fhello\\u0020world\\u00200123\\u003B\\u6C49\\u5B57\\uFF1B\\u2028\\u2028\\u000D\\u000A\\u003Cscript\\u003E\\u003C\\u002Fscirpt\\u003E\"}";
String json = JSON.toJSONString(vo, SerializerFeature.BrowserSecure);
Assert.assertEquals(expect, json);
Assert.assertEquals(value, JSON.parseObject(json, VO.class).getValue());
}
public static class VO {
String value;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
}
@@ -14,4 +14,12 @@ public class SerializerFeatureTest extends TestCase {
feature = SerializerFeature.config(feature, SerializerFeature.BrowserCompatible, false);
Assert.assertEquals(false, SerializerFeature.isEnabled(feature, SerializerFeature.BrowserCompatible));
}
public void test_1 () throws Exception {
int feature = 0;
feature = SerializerFeature.config(feature, SerializerFeature.BrowserSecure, true);
Assert.assertEquals(true, SerializerFeature.isEnabled(feature, SerializerFeature.BrowserSecure));
feature = SerializerFeature.config(feature, SerializerFeature.BrowserSecure, false);
Assert.assertEquals(false, SerializerFeature.isEnabled(feature, SerializerFeature.BrowserSecure));
}
}