diff --git a/pom.xml b/pom.xml index fff128748..25abda766 100755 --- a/pom.xml +++ b/pom.xml @@ -308,6 +308,13 @@ 2.1.5 test + + + org.springframework + spring-test + 3.1.1.RELEASE + test + diff --git a/src/main/java/com/alibaba/fastjson/JSONObject.java b/src/main/java/com/alibaba/fastjson/JSONObject.java index cb130bede..55f096a03 100755 --- a/src/main/java/com/alibaba/fastjson/JSONObject.java +++ b/src/main/java/com/alibaba/fastjson/JSONObject.java @@ -43,7 +43,6 @@ import java.util.Set; import com.alibaba.fastjson.annotation.JSONField; import com.alibaba.fastjson.parser.ParserConfig; -import com.alibaba.fastjson.util.AntiCollisionHashMap; import com.alibaba.fastjson.util.TypeUtils; /** @@ -76,7 +75,7 @@ public class JSONObject extends JSON implements Map, JSONAware, if (ordered) { map = new LinkedHashMap(initialCapacity); } else { - map = new AntiCollisionHashMap(initialCapacity); + map = new HashMap(initialCapacity); } } diff --git a/src/main/java/com/alibaba/fastjson/JSONReader.java b/src/main/java/com/alibaba/fastjson/JSONReader.java index 904c79d4d..8228aa159 100644 --- a/src/main/java/com/alibaba/fastjson/JSONReader.java +++ b/src/main/java/com/alibaba/fastjson/JSONReader.java @@ -1,11 +1,16 @@ package com.alibaba.fastjson; +import static com.alibaba.fastjson.JSONStreamContext.ArrayValue; +import static com.alibaba.fastjson.JSONStreamContext.PropertyKey; +import static com.alibaba.fastjson.JSONStreamContext.PropertyValue; +import static com.alibaba.fastjson.JSONStreamContext.StartArray; +import static com.alibaba.fastjson.JSONStreamContext.StartObject; + import java.io.Closeable; import java.io.Reader; import java.lang.reflect.Type; import java.util.Map; -import static com.alibaba.fastjson.JSONStreamContext.*; import com.alibaba.fastjson.parser.DefaultJSONParser; import com.alibaba.fastjson.parser.Feature; import com.alibaba.fastjson.parser.JSONLexer; @@ -19,7 +24,7 @@ public class JSONReader implements Closeable { private JSONStreamContext context; public JSONReader(Reader reader){ - this(new DefaultJSONParser(new JSONReaderScanner(reader))); + this(new JSONReaderScanner(reader)); } public JSONReader(JSONLexer lexer){ @@ -67,7 +72,7 @@ public class JSONReader implements Closeable { } private void startStructure() { - int state = context.getState(); + final int state = context.getState(); switch (state) { case PropertyKey: parser.accept(JSONToken.COLON); diff --git a/src/main/java/com/alibaba/fastjson/parser/CharTypes.java b/src/main/java/com/alibaba/fastjson/parser/CharTypes.java index dcffeeca1..6968be18d 100755 --- a/src/main/java/com/alibaba/fastjson/parser/CharTypes.java +++ b/src/main/java/com/alibaba/fastjson/parser/CharTypes.java @@ -121,27 +121,4 @@ public final class CharTypes { '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; - } } diff --git a/src/main/java/com/alibaba/fastjson/parser/DefaultJSONParser.java b/src/main/java/com/alibaba/fastjson/parser/DefaultJSONParser.java index 2d75fee1e..75f8a40a9 100755 --- a/src/main/java/com/alibaba/fastjson/parser/DefaultJSONParser.java +++ b/src/main/java/com/alibaba/fastjson/parser/DefaultJSONParser.java @@ -392,7 +392,7 @@ public class DefaultJSONParser extends AbstractJSONParser implements Closeable { if (lexer.token() == JSONToken.LITERAL_INT) { value = lexer.integerValue(); } else { - value = lexer.decimalValue(); + value = lexer.numberValue(); } object.put(key, value); diff --git a/src/main/java/com/alibaba/fastjson/parser/JSONLexer.java b/src/main/java/com/alibaba/fastjson/parser/JSONLexer.java index 69813cef2..ebb64d6cf 100755 --- a/src/main/java/com/alibaba/fastjson/parser/JSONLexer.java +++ b/src/main/java/com/alibaba/fastjson/parser/JSONLexer.java @@ -21,6 +21,7 @@ import static com.alibaba.fastjson.parser.JSONToken.EOF; import static com.alibaba.fastjson.parser.JSONToken.ERROR; import static com.alibaba.fastjson.parser.JSONToken.LBRACE; import static com.alibaba.fastjson.parser.JSONToken.LBRACKET; +import static com.alibaba.fastjson.parser.JSONToken.LITERAL_STRING; import static com.alibaba.fastjson.parser.JSONToken.LPAREN; import static com.alibaba.fastjson.parser.JSONToken.RBRACE; import static com.alibaba.fastjson.parser.JSONToken.RBRACKET; @@ -342,13 +343,13 @@ public abstract class JSONLexer implements Closeable { break; } } - + public final void nextIdent() { while (isWhitespace(ch)) { next(); } if (ch == '_' || Character.isLetter(ch)) { - scanIdent(); + scanIdent(); } else { nextToken(); } @@ -582,8 +583,6 @@ public abstract class JSONLexer implements Closeable { public abstract boolean isEOF(); - public abstract String symbol(SymbolTable symbolTable); - public final char getCurrent() { return ch; } @@ -631,17 +630,302 @@ public abstract class JSONLexer implements Closeable { return scanSymbolUnQuoted(symbolTable); } - public abstract String scanSymbol(final SymbolTable symbolTable, final char quote); +// public abstract String scanSymbol(final SymbolTable symbolTable, final char quote); + + protected abstract void arrayCopy(int srcPos, char[] dest, int destPos, int length); + + public final String scanSymbol(final SymbolTable symbolTable, final char quote) { + int hash = 0; + + np = bp; + sp = 0; + boolean hasSpecial = false; + char chLocal; + for (;;) { + chLocal = charAt(++bp); + + if (chLocal == quote) { + break; + } + + if (chLocal == EOI) { + throw new JSONException("unclosed.str"); + } + + if (chLocal == '\\') { + if (!hasSpecial) { + hasSpecial = true; + + if (sp >= sbuf.length) { + int newCapcity = sbuf.length * 2; + if (sp > newCapcity) { + newCapcity = sp; + } + char[] newsbuf = new char[newCapcity]; + System.arraycopy(sbuf, 0, newsbuf, 0, sbuf.length); + sbuf = newsbuf; + } + + // text.getChars(np + 1, np + 1 + sp, sbuf, 0); +// System.arraycopy(this.buf, np + 1, sbuf, 0, sp); + arrayCopy(np + 1, sbuf, 0, sp); + } + + chLocal = charAt(++bp); + + switch (chLocal) { + case '"': + hash = 31 * hash + (int) '"'; + putChar('"'); + break; + case '\\': + hash = 31 * hash + (int) '\\'; + putChar('\\'); + break; + case '/': + hash = 31 * hash + (int) '/'; + putChar('/'); + break; + case 'b': + hash = 31 * hash + (int) '\b'; + putChar('\b'); + break; + case 'f': + case 'F': + hash = 31 * hash + (int) '\f'; + putChar('\f'); + break; + case 'n': + hash = 31 * hash + (int) '\n'; + putChar('\n'); + break; + case 'r': + hash = 31 * hash + (int) '\r'; + putChar('\r'); + break; + case 't': + hash = 31 * hash + (int) '\t'; + putChar('\t'); + break; + case 'u': + char c1 = chLocal = charAt(++bp); + char c2 = chLocal = charAt(++bp); + char c3 = chLocal = charAt(++bp); + char c4 = chLocal = charAt(++bp); + int val = Integer.parseInt(new String(new char[] { c1, c2, c3, c4 }), 16); + hash = 31 * hash + val; + putChar((char) val); + break; + default: + this.ch = chLocal; + throw new JSONException("unclosed.str.lit"); + } + continue; + } + + hash = 31 * hash + chLocal; + + if (!hasSpecial) { + sp++; + continue; + } + + if (sp == sbuf.length) { + putChar(chLocal); + } else { + sbuf[sp++] = chLocal; + } + } + + token = LITERAL_STRING; + this.next(); + + if (!hasSpecial) { + // return this.text.substring(np + 1, np + 1 + sp).intern(); + return addSymbol(np + 1, sp, hash, symbolTable); + } else { + return symbolTable.addSymbol(sbuf, 0, sp, hash); + } + } public final void resetStringPosition() { this.sp = 0; } - public abstract String scanSymbolUnQuoted(final SymbolTable symbolTable); + public final String scanSymbolUnQuoted(final SymbolTable symbolTable) { + final boolean[] firstIdentifierFlags = CharTypes.firstIdentifierFlags; + final char first = ch; + + final boolean firstFlag = ch >= firstIdentifierFlags.length || firstIdentifierFlags[first]; + if (!firstFlag) { + throw new JSONException("illegal identifier : " + ch); + } + + final boolean[] identifierFlags = CharTypes.identifierFlags; + + int hash = first; + + np = bp; + sp = 1; + char chLocal; + for (;;) { + chLocal = charAt(++bp); + + if (chLocal < identifierFlags.length) { + if (!identifierFlags[chLocal]) { + break; + } + } + + hash = 31 * hash + chLocal; + + sp++; + continue; + } + + this.ch = charAt(bp); + token = JSONToken.IDENTIFIER; + + final int NULL_HASH = 3392903; + if (sp == 4 && hash == NULL_HASH && charAt(np) == 'n' && charAt(np + 1) == 'u' && charAt(np + 2) == 'l' + && charAt(np + 3) == 'l') { + return null; + } + + // return text.substring(np, np + sp).intern(); + + return this.addSymbol(np, sp, hash, symbolTable); +// return symbolTable.addSymbol(buf, np, sp, hash); + } protected abstract void copyTo(int offset, int count, char[] dest); - public abstract void scanString(); + public final void scanString() { + np = bp; + hasSpecial = false; + char ch; + for (;;) { + ch = charAt(++bp); + + if (ch == '\"') { + break; + } + + if (ch == '\\') { + if (!hasSpecial) { + hasSpecial = true; + + if (sp >= sbuf.length) { + int newCapcity = sbuf.length * 2; + if (sp > newCapcity) { + newCapcity = sp; + } + char[] newsbuf = new char[newCapcity]; + System.arraycopy(sbuf, 0, newsbuf, 0, sbuf.length); + sbuf = newsbuf; + } + + copyTo(np + 1, sp, sbuf); +// text.getChars(np + 1, np + 1 + sp, sbuf, 0); + // System.arraycopy(buf, np + 1, sbuf, 0, sp); + } + + ch = charAt(++bp); + + switch (ch) { + case '0': + putChar('\0'); + break; + case '1': + putChar('\1'); + break; + case '2': + putChar('\2'); + break; + 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 '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 'r': // 13 + putChar('\r'); + break; + case '"': // 34 + putChar('"'); + break; + case '\'': // 39 + putChar('\''); + break; + case '/': // 47 + putChar('/'); + break; + case '\\': // 92 + putChar('\\'); + break; + case 'x': + char x1 = ch = charAt(++bp); + char x2 = ch = charAt(++bp); + + int x_val = digits[x1] * 16 + digits[x2]; + char x_char = (char) x_val; + putChar(x_char); + break; + case 'u': + char u1 = ch = charAt(++bp); + char u2 = ch = charAt(++bp); + char u3 = ch = charAt(++bp); + char u4 = ch = charAt(++bp); + int val = Integer.parseInt(new String(new char[] { u1, u2, u3, u4 }), 16); + putChar((char) val); + break; + default: + this.ch = ch; + throw new JSONException("unclosed string : " + ch); + } + continue; + } + + if (!hasSpecial) { + sp++; + continue; + } + + if (sp == sbuf.length) { + putChar(ch); + } else { + sbuf[sp++] = ch; + } + } + + token = JSONToken.LITERAL_STRING; + this.ch = charAt(++bp); + } public Calendar getCalendar() { return this.calendar; @@ -719,9 +1003,77 @@ public abstract class JSONLexer implements Closeable { return charAt(np + 1) == '$' && charAt(np + 2) == 'r' && charAt(np + 3) == 'e' && charAt(np + 4) == 'f'; } - public abstract int scanType(String type); + protected final static char[] typeFieldName = ("\"" + JSON.DEFAULT_TYPE_KEY + "\":\"").toCharArray(); + public final int scanType(String type) { + matchStat = UNKOWN; - public abstract boolean matchField(char[] fieldName); + if (!charArrayCompare(typeFieldName)) { + return NOT_MATCH_NAME; + } + + int bpLocal = this.bp + typeFieldName.length; + + final int typeLength = type.length(); + for (int i = 0; i < typeLength; ++i) { + if (type.charAt(i) != charAt(bpLocal + i)) { + return NOT_MATCH; + } + } + bpLocal += typeLength; + if (charAt(bpLocal) != '"') { + return NOT_MATCH; + } + + this.ch = charAt(++bpLocal); + + if (ch == ',') { + this.ch = charAt(++bpLocal); + this.bp = bpLocal; + token = JSONToken.COMMA; + return VALUE; + } else if (ch == '}') { + ch = charAt(++bpLocal); + if (ch == ',') { + token = JSONToken.COMMA; + this.ch = charAt(++bpLocal); + } else if (ch == ']') { + token = JSONToken.RBRACKET; + this.ch = charAt(++bpLocal); + } else if (ch == '}') { + token = JSONToken.RBRACE; + this.ch = charAt(++bpLocal); + } else if (ch == EOI) { + token = JSONToken.EOF; + } else { + return NOT_MATCH; + } + matchStat = END; + } + + this.bp = bpLocal; + return matchStat; + } + + public final boolean matchField(char[] fieldName) { + if (!charArrayCompare(fieldName)) { + return false; + } + + bp = bp + fieldName.length; + ch = charAt(bp); + + if (ch == '{') { + next(); + token = JSONToken.LBRACE; + } else if (ch == '[') { + next(); + token = JSONToken.LBRACKET; + } else { + nextToken(); + } + + return true; + } public abstract int indexOf(char ch, int startIndex); @@ -1584,7 +1936,29 @@ public abstract class JSONLexer implements Closeable { } } - public abstract void scanIdent(); + public final void scanIdent() { + np = bp - 1; + hasSpecial = false; + + for (;;) { + sp++; + + next(); + if (Character.isLetterOrDigit(ch)) { + continue; + } + + String ident = stringVal(); + + Integer tok = keywods.getKeyword(ident); + if (tok != null) { + token = tok; + } else { + token = JSONToken.IDENTIFIER; + } + return; + } + } public abstract String stringVal(); @@ -1618,7 +1992,132 @@ public abstract class JSONLexer implements Closeable { } } - public abstract void scanStringSingleQuote(); + public final void scanStringSingleQuote() { + np = bp; + hasSpecial = false; + char chLocal; + for (;;) { + chLocal = charAt(++bp); + + if (chLocal == '\'') { + break; + } + + if (chLocal == EOI) { + throw new JSONException("unclosed single-quote string"); + } + + if (chLocal == '\\') { + if (!hasSpecial) { + hasSpecial = true; + + if (sp > sbuf.length) { + char[] newsbuf = new char[sp * 2]; + System.arraycopy(sbuf, 0, newsbuf, 0, sbuf.length); + sbuf = newsbuf; + } + + //text.getChars(offset, offset + count, dest, 0); + this.copyTo(np + 1, sp, sbuf); + // System.arraycopy(buf, np + 1, sbuf, 0, sp); + } + + chLocal = charAt(++bp); + + switch (chLocal) { + case '0': + putChar('\0'); + break; + case '1': + putChar('\1'); + break; + case '2': + putChar('\2'); + break; + 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 '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 'r': // 13 + putChar('\r'); + break; + case '"': // 34 + putChar('"'); + break; + case '\'': // 39 + putChar('\''); + break; + case '/': // 47 + putChar('/'); + break; + case '\\': // 92 + putChar('\\'); + break; + case 'x': + char x1 = chLocal = charAt(++bp); + char x2 = chLocal = charAt(++bp); + + int x_val = digits[x1] * 16 + digits[x2]; + char x_char = (char) x_val; + putChar(x_char); + break; + case 'u': + char c1 = chLocal = charAt(++bp); + char c2 = chLocal = charAt(++bp); + char c3 = chLocal = charAt(++bp); + char c4 = chLocal = charAt(++bp); + int val = Integer.parseInt(new String(new char[] { c1, c2, c3, c4 }), 16); + putChar((char) val); + break; + default: + this.ch = chLocal; + throw new JSONException("unclosed single-quote string"); + } + continue; + } + + if (!hasSpecial) { + sp++; + continue; + } + + if (sp == sbuf.length) { + putChar(chLocal); + } else { + sbuf[sp++] = chLocal; + } + } + + token = LITERAL_STRING; + this.next(); + } public final void scanSet() { if (ch != 'S') { @@ -1811,6 +2310,21 @@ public abstract class JSONLexer implements Closeable { return new BigDecimal(numberString()); } + public final Number numberValue() { + char type = charAt(np + sp - 1); + + String str = this.numberString(); + + switch (type) { + case 'D': + return Double.parseDouble(str); + case 'F': + return Float.parseFloat(str); + default: + return new BigDecimal(str); + } + } + public static final boolean isWhitespace(char ch) { // 专门调整了判断顺序 return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t' || ch == '\f' || ch == '\b'; diff --git a/src/main/java/com/alibaba/fastjson/parser/JSONReaderScanner.java b/src/main/java/com/alibaba/fastjson/parser/JSONReaderScanner.java index cd32b820e..087a963a2 100644 --- a/src/main/java/com/alibaba/fastjson/parser/JSONReaderScanner.java +++ b/src/main/java/com/alibaba/fastjson/parser/JSONReaderScanner.java @@ -15,8 +15,6 @@ */ package com.alibaba.fastjson.parser; -import static com.alibaba.fastjson.parser.JSONToken.LITERAL_STRING; - import java.io.CharArrayReader; import java.io.IOException; import java.io.Reader; @@ -181,347 +179,10 @@ public final class JSONReaderScanner extends JSONLexer { return ch = buf[index]; } - public void scanString() { - np = bp; - hasSpecial = false; - - int offset = 0; - - char chLocal; - for (;;) { - chLocal = charAt(bp + (++offset)); - - if (chLocal == '\"') { - break; - } - - if (chLocal == '\\') { - if (!hasSpecial) { - hasSpecial = true; - - if (sp >= sbuf.length) { - int newCapcity = sbuf.length * 2; - if (sp > newCapcity) { - newCapcity = sp; - } - char[] newsbuf = new char[newCapcity]; - System.arraycopy(sbuf, 0, newsbuf, 0, sbuf.length); - sbuf = newsbuf; - } - - copyTo(bp + 1, sp, sbuf); - } - - chLocal = charAt(bp + (++offset)); - - switch (chLocal) { - case '"': - putChar('"'); - break; - case '\'': - putChar('\''); - break; - case '\\': - putChar('\\'); - break; - case '/': - putChar('/'); - break; - case 'b': - putChar('\b'); - break; - case 'f': - case 'F': - putChar('\f'); - break; - case 'n': - putChar('\n'); - break; - case 'r': - putChar('\r'); - break; - case 't': - putChar('\t'); - break; - case 'x': - char x1 = chLocal = charAt(++bp); - char x2 = chLocal = charAt(++bp); - - int x_val = digits[x1] * 16 + digits[x2]; - char x_char = (char) x_val; - putChar(x_char); - break; - case 'u': - char u1 = chLocal = charAt(++bp); - char u2 = chLocal = charAt(++bp); - char u3 = chLocal = charAt(++bp); - char u4 = chLocal = charAt(++bp); - int val = Integer.parseInt(new String(new char[] { u1, u2, u3, u4 }), 16); - putChar((char) val); - break; - default: - this.ch = chLocal; - throw new JSONException("unclosed string : " + chLocal); - } - continue; - } - - if (!hasSpecial) { - sp++; - continue; - } - - if (sp == sbuf.length) { - putChar(chLocal); - } else { - sbuf[sp++] = chLocal; - } - } - - bp += offset; - token = LITERAL_STRING; - this.next(); - } - - public final void scanStringSingleQuote() { - np = bp; - hasSpecial = false; - - int offset = 0; - - char chLocal; - for (;;) { - chLocal = charAt(bp + (++offset)); - - if (chLocal == '\'') { - break; - } - - if (chLocal == '\\') { - if (!hasSpecial) { - hasSpecial = true; - - if (sp >= sbuf.length) { - int newCapcity = sbuf.length * 2; - if (sp > newCapcity) { - newCapcity = sp; - } - char[] newsbuf = new char[newCapcity]; - System.arraycopy(sbuf, 0, newsbuf, 0, sbuf.length); - sbuf = newsbuf; - } - - copyTo(bp + 1, sp, sbuf); - } - - chLocal = charAt(bp + (++offset)); - - switch (chLocal) { - case '"': - putChar('"'); - break; - case '\'': - putChar('\''); - break; - case '\\': - putChar('\\'); - break; - case '/': - putChar('/'); - break; - case 'b': - putChar('\b'); - break; - case 'f': - case 'F': - putChar('\f'); - break; - case 'n': - putChar('\n'); - break; - case 'r': - putChar('\r'); - break; - case 't': - putChar('\t'); - break; - case 'x': - char x1 = chLocal = charAt(++bp); - char x2 = chLocal = charAt(++bp); - - int x_val = digits[x1] * 16 + digits[x2]; - char x_char = (char) x_val; - putChar(x_char); - break; - case 'u': - char u1 = chLocal = charAt(++bp); - char u2 = chLocal = charAt(++bp); - char u3 = chLocal = charAt(++bp); - char u4 = chLocal = charAt(++bp); - int val = Integer.parseInt(new String(new char[] { u1, u2, u3, u4 }), 16); - putChar((char) val); - break; - default: - this.ch = chLocal; - throw new JSONException("unclosed string : " + chLocal); - } - continue; - } - - if (!hasSpecial) { - sp++; - continue; - } - - if (sp == sbuf.length) { - putChar(chLocal); - } else { - sbuf[sp++] = chLocal; - } - } - - bp += offset; - token = LITERAL_STRING; - this.next(); - } - protected final void copyTo(int offset, int count, char[] dest) { System.arraycopy(buf, offset, dest, 0, count); } - public final String scanSymbolUnQuoted(final SymbolTable symbolTable) { - final boolean[] firstIdentifierFlags = CharTypes.firstIdentifierFlags; - final char first = ch; - - final boolean firstFlag = ch >= firstIdentifierFlags.length || firstIdentifierFlags[first]; - if (!firstFlag) { - throw new JSONException("illegal identifier : " + ch); - } - - final boolean[] identifierFlags = CharTypes.identifierFlags; - - int hash = first; - - np = bp; - sp = 1; - char chLocal; - for (;;) { - chLocal = charAt(++bp); - - if (chLocal < identifierFlags.length) { - if (!identifierFlags[chLocal]) { - break; - } - } - - hash = 31 * hash + chLocal; - - sp++; - continue; - } - - this.ch = charAt(bp); - token = JSONToken.IDENTIFIER; - - final int NULL_HASH = 3392903; - if (sp == 4 && hash == NULL_HASH && charAt(np) == 'n' && charAt(np + 1) == 'u' && charAt(np + 2) == 'l' - && charAt(np + 3) == 'l') { - return null; - } - - // return text.substring(np, np + sp).intern(); - - return symbolTable.addSymbol(buf, np, sp, hash); - } - - protected final static char[] typeFieldName = ("\"" + JSON.DEFAULT_TYPE_KEY + "\":\"").toCharArray(); - - public final int scanType(String type) { - matchStat = UNKOWN; - - if (!charArrayCompare(buf, bp, typeFieldName)) { - return NOT_MATCH_NAME; - } - - int bpLocal = this.bp + typeFieldName.length; - - final int typeLength = type.length(); - for (int i = 0; i < typeLength; ++i) { - if (type.charAt(i) != charAt(bpLocal + i)) { - return NOT_MATCH; - } - } - bpLocal += typeLength; - if (charAt(bpLocal) != '"') { - return NOT_MATCH; - } - - this.ch = charAt(++bpLocal); - - if (ch == ',') { - this.ch = charAt(++bpLocal); - this.bp = bpLocal; - token = JSONToken.COMMA; - return VALUE; - } else if (ch == '}') { - ch = charAt(++bpLocal); - if (ch == ',') { - token = JSONToken.COMMA; - this.ch = charAt(++bpLocal); - } else if (ch == ']') { - token = JSONToken.RBRACKET; - this.ch = charAt(++bpLocal); - } else if (ch == '}') { - token = JSONToken.RBRACE; - this.ch = charAt(++bpLocal); - } else if (ch == EOI) { - token = JSONToken.EOF; - } else { - return NOT_MATCH; - } - matchStat = END; - } - - this.bp = bpLocal; - return matchStat; - } - - public final boolean matchField(char[] fieldName) { - if (!charArrayCompare(fieldName)) { - return false; - } - - bp = bp + fieldName.length; - ch = charAt(bp); - - if (ch == '{') { - next(); - token = JSONToken.LBRACE; - } else if (ch == '[') { - next(); - token = JSONToken.LBRACKET; - } else { - nextToken(); - } - - return true; - } - - // sun.misc.Unsafe.byteArrayCompare(byte[], int, int, byte[], int, int) - static final boolean charArrayCompare(char[] src, int offset, char[] dest) { - final int destLen = dest.length; - if (destLen + offset > src.length) { - return false; - } - - for (int i = 0; i < destLen; ++i) { - if (dest[i] != src[offset + i]) { - return false; - } - } - - return true; - } public final boolean charArrayCompare(char[] chars) { for (int i = 0; i < chars.length; ++i) { @@ -537,145 +198,8 @@ public final class JSONReaderScanner extends JSONLexer { return Base64.decodeFast(buf, np + 1, sp); } - // public int scanField2(char[] fieldName, Object object, FieldDeserializer fieldDeserializer) { - // return NOT_MATCH; - // } - - public final String scanSymbol(final SymbolTable symbolTable, final char quote) { - int hash = 0; - - np = bp; - sp = 0; - boolean hasSpecial = false; - char chLocal; - for (;;) { - chLocal = charAt(++bp); - - if (chLocal == quote) { - break; - } - - if (chLocal == EOI) { - throw new JSONException("unclosed.str"); - } - - if (chLocal == '\\') { - if (!hasSpecial) { - hasSpecial = true; - - if (sp >= sbuf.length) { - int newCapcity = sbuf.length * 2; - if (sp > newCapcity) { - newCapcity = sp; - } - char[] newsbuf = new char[newCapcity]; - System.arraycopy(sbuf, 0, newsbuf, 0, sbuf.length); - sbuf = newsbuf; - } - - // text.getChars(np + 1, np + 1 + sp, sbuf, 0); - System.arraycopy(this.buf, np + 1, sbuf, 0, sp); - } - - chLocal = charAt(++bp); - - switch (chLocal) { - case '"': - hash = 31 * hash + (int) '"'; - putChar('"'); - break; - case '\\': - hash = 31 * hash + (int) '\\'; - putChar('\\'); - break; - case '/': - hash = 31 * hash + (int) '/'; - putChar('/'); - break; - case 'b': - hash = 31 * hash + (int) '\b'; - putChar('\b'); - break; - case 'f': - case 'F': - hash = 31 * hash + (int) '\f'; - putChar('\f'); - break; - case 'n': - hash = 31 * hash + (int) '\n'; - putChar('\n'); - break; - case 'r': - hash = 31 * hash + (int) '\r'; - putChar('\r'); - break; - case 't': - hash = 31 * hash + (int) '\t'; - putChar('\t'); - break; - case 'u': - char c1 = chLocal = charAt(++bp); - char c2 = chLocal = charAt(++bp); - char c3 = chLocal = charAt(++bp); - char c4 = chLocal = charAt(++bp); - int val = Integer.parseInt(new String(new char[] { c1, c2, c3, c4 }), 16); - hash = 31 * hash + val; - putChar((char) val); - break; - default: - this.ch = chLocal; - throw new JSONException("unclosed.str.lit"); - } - continue; - } - - hash = 31 * hash + chLocal; - - if (!hasSpecial) { - sp++; - continue; - } - - if (sp == sbuf.length) { - putChar(chLocal); - } else { - sbuf[sp++] = chLocal; - } - } - - token = LITERAL_STRING; - this.next(); - - if (!hasSpecial) { - // return this.text.substring(np + 1, np + 1 + sp).intern(); - return symbolTable.addSymbol(buf, np + 1, sp, hash); - } else { - return symbolTable.addSymbol(sbuf, 0, sp, hash); - } - } - - public void scanIdent() { - np = bp - 1; - hasSpecial = false; - - for (;;) { - sp++; - - next(); - if (Character.isLetterOrDigit(ch)) { - continue; - } - - String ident = stringVal(); - - Integer tok = keywods.getKeyword(ident); - if (tok != null) { - token = tok; - } else { - token = JSONToken.IDENTIFIER; - } - return; - } + protected final void arrayCopy(int srcPos, char[] dest, int destPos, int length) { + System.arraycopy(buf, srcPos, dest, destPos, length); } /** @@ -695,23 +219,6 @@ public final class JSONReaderScanner extends JSONLexer { // return text.substring(offset, offset + count); } - public final String symbol(SymbolTable symbolTable) { - if (symbolTable == null) { - if (!hasSpecial) { - // return text.substring(np + 1, np + 1 + sp); - return new String(buf, np + 1, sp); - } else { - return new String(sbuf, 0, sp); - } - } - - if (!hasSpecial) { - return symbolTable.addSymbol(buf, np + 1, sp); - } else { - return symbolTable.addSymbol(sbuf, 0, sp); - } - } - public final String numberString() { char chLocal = charAt(np + sp - 1); @@ -720,7 +227,6 @@ public final class JSONReaderScanner extends JSONLexer { sp--; } - // return text.substring(np, np + sp); return new String(buf, np, sp); } diff --git a/src/main/java/com/alibaba/fastjson/parser/JSONScanner.java b/src/main/java/com/alibaba/fastjson/parser/JSONScanner.java index ae52b41ae..e90884ca4 100755 --- a/src/main/java/com/alibaba/fastjson/parser/JSONScanner.java +++ b/src/main/java/com/alibaba/fastjson/parser/JSONScanner.java @@ -15,8 +15,6 @@ */ package com.alibaba.fastjson.parser; -import static com.alibaba.fastjson.parser.JSONToken.LITERAL_STRING; - import java.util.ArrayList; import java.util.Calendar; import java.util.Collection; @@ -73,254 +71,10 @@ public final class JSONScanner extends JSONLexer { this(new String(input, 0, inputLength), features); } - public final void scanStringSingleQuote() { - np = bp; - hasSpecial = false; - char chLocal; - for (;;) { - chLocal = charAt(++bp); - - if (chLocal == '\'') { - break; - } - - if (chLocal == EOI) { - throw new JSONException("unclosed single-quote string"); - } - - if (chLocal == '\\') { - if (!hasSpecial) { - hasSpecial = true; - - if (sp > sbuf.length) { - char[] newsbuf = new char[sp * 2]; - System.arraycopy(sbuf, 0, newsbuf, 0, sbuf.length); - sbuf = newsbuf; - } - - text.getChars(np + 1, np + 1 + sp, sbuf, 0); - // System.arraycopy(buf, np + 1, sbuf, 0, sp); - } - - chLocal = charAt(++bp); - - switch (chLocal) { - case '0': - putChar('\0'); - break; - case '1': - putChar('\1'); - break; - case '2': - putChar('\2'); - break; - 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 '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 'r': // 13 - putChar('\r'); - break; - case '"': // 34 - putChar('"'); - break; - case '\'': // 39 - putChar('\''); - break; - case '/': // 47 - putChar('/'); - break; - case '\\': // 92 - putChar('\\'); - break; - case 'x': - char x1 = chLocal = charAt(++bp); - char x2 = chLocal = charAt(++bp); - - int x_val = digits[x1] * 16 + digits[x2]; - char x_char = (char) x_val; - putChar(x_char); - break; - case 'u': - char c1 = chLocal = charAt(++bp); - char c2 = chLocal = charAt(++bp); - char c3 = chLocal = charAt(++bp); - char c4 = chLocal = charAt(++bp); - int val = Integer.parseInt(new String(new char[] { c1, c2, c3, c4 }), 16); - putChar((char) val); - break; - default: - this.ch = chLocal; - throw new JSONException("unclosed single-quote string"); - } - continue; - } - - if (!hasSpecial) { - sp++; - continue; - } - - if (sp == sbuf.length) { - putChar(chLocal); - } else { - sbuf[sp++] = chLocal; - } - } - - token = LITERAL_STRING; - this.next(); - } - protected final void copyTo(int offset, int count, char[] dest) { text.getChars(offset, offset + count, dest, 0); } - public final String scanSymbolUnQuoted(final SymbolTable symbolTable) { - final boolean[] firstIdentifierFlags = CharTypes.firstIdentifierFlags; - final char first = ch; - - final boolean firstFlag = ch >= firstIdentifierFlags.length || firstIdentifierFlags[first]; - if (!firstFlag) { - throw new JSONException("illegal identifier : " + ch); - } - - final boolean[] identifierFlags = CharTypes.identifierFlags; - - int hash = first; - - np = bp; - sp = 1; - char chLocal; - for (;;) { - chLocal = charAt(++bp); - - if (chLocal < identifierFlags.length) { - if (!identifierFlags[chLocal]) { - break; - } - } - - hash = 31 * hash + chLocal; - - sp++; - continue; - } - - this.ch = charAt(bp); - token = JSONToken.IDENTIFIER; - - final int NULL_HASH = 3392903; - if (sp == 4 && hash == NULL_HASH && charAt(np) == 'n' && charAt(np + 1) == 'u' && charAt(np + 2) == 'l' - && charAt(np + 3) == 'l') { - return null; - } - - return text.substring(np, np + sp).intern(); - - // return symbolTable.addSymbol(buf, np, sp, hash); - } - - protected final static char[] typeFieldName = ("\"" + JSON.DEFAULT_TYPE_KEY + "\":\"").toCharArray(); - - public final int scanType(String type) { - matchStat = UNKOWN; - - if (!charArrayCompare(text, bp, typeFieldName)) { - return NOT_MATCH_NAME; - } - - int bpLocal = this.bp + typeFieldName.length; - - final int typeLength = type.length(); - for (int i = 0; i < typeLength; ++i) { - if (type.charAt(i) != charAt(bpLocal + i)) { - return NOT_MATCH; - } - } - bpLocal += typeLength; - if (charAt(bpLocal) != '"') { - return NOT_MATCH; - } - - this.ch = charAt(++bpLocal); - - if (ch == ',') { - this.ch = charAt(++bpLocal); - this.bp = bpLocal; - token = JSONToken.COMMA; - return VALUE; - } else if (ch == '}') { - ch = charAt(++bpLocal); - if (ch == ',') { - token = JSONToken.COMMA; - this.ch = charAt(++bpLocal); - } else if (ch == ']') { - token = JSONToken.RBRACKET; - this.ch = charAt(++bpLocal); - } else if (ch == '}') { - token = JSONToken.RBRACE; - this.ch = charAt(++bpLocal); - } else if (ch == EOI) { - token = JSONToken.EOF; - } else { - return NOT_MATCH; - } - matchStat = END; - } - - this.bp = bpLocal; - return matchStat; - } - - public final boolean matchField(char[] fieldName) { - if (!charArrayCompare(fieldName)) { - return false; - } - - bp = bp + fieldName.length; - ch = charAt(bp); - - if (ch == '{') { - next(); - token = JSONToken.LBRACE; - } else if (ch == '[') { - next(); - token = JSONToken.LBRACKET; - } else { - nextToken(); - } - - return true; - } - static final boolean charArrayCompare(String src, int offset, char[] dest) { final int destLen = dest.length; if (destLen + offset > src.length()) { @@ -352,153 +106,12 @@ public final class JSONScanner extends JSONLexer { return Base64.decodeFast(text, np + 1, sp); } - // public int scanField2(char[] fieldName, Object object, FieldDeserializer fieldDeserializer) { - // return NOT_MATCH; - // } - - public final String scanSymbol(final SymbolTable symbolTable, final char quote) { - int hash = 0; - - np = bp; - sp = 0; - boolean hasSpecial = false; - char chLocal; - for (;;) { - chLocal = charAt(++bp); - - if (chLocal == quote) { - break; - } - - if (chLocal == EOI) { - throw new JSONException("unclosed.str"); - } - - if (chLocal == '\\') { - if (!hasSpecial) { - hasSpecial = true; - - if (sp >= sbuf.length) { - int newCapcity = sbuf.length * 2; - if (sp > newCapcity) { - newCapcity = sp; - } - char[] newsbuf = new char[newCapcity]; - System.arraycopy(sbuf, 0, newsbuf, 0, sbuf.length); - sbuf = newsbuf; - } - - text.getChars(np + 1, np + 1 + sp, sbuf, 0); - // System.arraycopy(buf, np + 1, sbuf, 0, sp); - } - - chLocal = charAt(++bp); - - switch (chLocal) { - case '"': - hash = 31 * hash + (int) '"'; - putChar('"'); - break; - case '\\': - hash = 31 * hash + (int) '\\'; - putChar('\\'); - break; - case '/': - hash = 31 * hash + (int) '/'; - putChar('/'); - break; - case 'b': - hash = 31 * hash + (int) '\b'; - putChar('\b'); - break; - case 'f': - case 'F': - hash = 31 * hash + (int) '\f'; - putChar('\f'); - break; - case 'n': - hash = 31 * hash + (int) '\n'; - putChar('\n'); - break; - case 'r': - hash = 31 * hash + (int) '\r'; - putChar('\r'); - break; - case 't': - hash = 31 * hash + (int) '\t'; - putChar('\t'); - break; - case 'u': - char c1 = chLocal = charAt(++bp); - char c2 = chLocal = charAt(++bp); - char c3 = chLocal = charAt(++bp); - char c4 = chLocal = charAt(++bp); - int val = Integer.parseInt(new String(new char[] { c1, c2, c3, c4 }), 16); - hash = 31 * hash + val; - putChar((char) val); - break; - default: - this.ch = chLocal; - throw new JSONException("unclosed.str.lit"); - } - continue; - } - - hash = 31 * hash + chLocal; - - if (!hasSpecial) { - sp++; - continue; - } - - if (sp == sbuf.length) { - putChar(chLocal); - } else { - sbuf[sp++] = chLocal; - } - } - - token = LITERAL_STRING; - this.next(); - - if (!hasSpecial) { - // return this.text.substring(np + 1, np + 1 + sp).intern(); - return symbolTable.addSymbol(text, np + 1, sp, hash); - } else { - return symbolTable.addSymbol(sbuf, 0, sp, hash); - } + protected void arrayCopy(int srcPos, char[] dest, int destPos, int length) { + text.getChars(srcPos, srcPos + length, dest, destPos); } - public void scanIdent() { - np = bp - 1; - hasSpecial = false; - - for (;;) { - sp++; - - next(); - if (Character.isLetterOrDigit(ch)) { - continue; - } - - String ident = stringVal(); - - Integer tok = keywods.getKeyword(ident); - if (tok != null) { - token = tok; - } else { - token = JSONToken.IDENTIFIER; - } - return; - } - } - - /** - * The value of a literal token, recorded as a string. For integers, leading 0x and 'l' suffixes are suppressed. - */ public final String stringVal() { if (!hasSpecial) { - // return new String(buf, np + 1, sp); return text.substring(np + 1, np + 1 + sp); } else { return new String(sbuf, 0, sp); @@ -509,25 +122,6 @@ public final class JSONScanner extends JSONLexer { return text.substring(offset, offset + count); } - // - - public final String symbol(SymbolTable symbolTable) { - if (symbolTable == null) { - if (!hasSpecial) { - return text.substring(np + 1, np + 1 + sp); - // return new String(buf, np + 1, sp); - } else { - return new String(sbuf, 0, sp); - } - } - - if (!hasSpecial) { - return symbolTable.addSymbol(text, np + 1, sp); - } else { - return symbolTable.addSymbol(sbuf, 0, sp); - } - } - public final String numberString() { char chLocal = charAt(np + sp - 1); @@ -537,7 +131,6 @@ public final class JSONScanner extends JSONLexer { } return text.substring(np, np + sp); - // return new String(buf, np, sp); } public final int ISO8601_LEN_0 = "0000-00-00".length(); @@ -1386,130 +979,4 @@ public final class JSONScanner extends JSONLexer { return value; } - - public final void scanString() { - np = bp; - hasSpecial = false; - char ch; - for (;;) { - ch = charAt(++bp); - - if (ch == '\"') { - break; - } - - if (ch == '\\') { - if (!hasSpecial) { - hasSpecial = true; - - if (sp >= sbuf.length) { - int newCapcity = sbuf.length * 2; - if (sp > newCapcity) { - newCapcity = sp; - } - char[] newsbuf = new char[newCapcity]; - System.arraycopy(sbuf, 0, newsbuf, 0, sbuf.length); - sbuf = newsbuf; - } - - text.getChars(np + 1, np + 1 + sp, sbuf, 0); - // System.arraycopy(buf, np + 1, sbuf, 0, sp); - } - - ch = charAt(++bp); - - switch (ch) { - case '0': - putChar('\0'); - break; - case '1': - putChar('\1'); - break; - case '2': - putChar('\2'); - break; - 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 '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 'r': // 13 - putChar('\r'); - break; - case '"': // 34 - putChar('"'); - break; - case '\'': // 39 - putChar('\''); - break; - case '/': // 47 - putChar('/'); - break; - case '\\': // 92 - putChar('\\'); - break; - case 'x': - char x1 = ch = charAt(++bp); - char x2 = ch = charAt(++bp); - - int x_val = digits[x1] * 16 + digits[x2]; - char x_char = (char) x_val; - putChar(x_char); - break; - case 'u': - char u1 = ch = charAt(++bp); - char u2 = ch = charAt(++bp); - char u3 = ch = charAt(++bp); - char u4 = ch = charAt(++bp); - int val = Integer.parseInt(new String(new char[] { u1, u2, u3, u4 }), 16); - putChar((char) val); - break; - default: - this.ch = ch; - throw new JSONException("unclosed string : " + ch); - } - continue; - } - - if (!hasSpecial) { - sp++; - continue; - } - - if (sp == sbuf.length) { - putChar(ch); - } else { - sbuf[sp++] = ch; - } - } - - token = LITERAL_STRING; - this.ch = charAt(++bp); - } } diff --git a/src/main/java/com/alibaba/fastjson/parser/ParserConfig.java b/src/main/java/com/alibaba/fastjson/parser/ParserConfig.java index 7c997e6c2..e386937c0 100755 --- a/src/main/java/com/alibaba/fastjson/parser/ParserConfig.java +++ b/src/main/java/com/alibaba/fastjson/parser/ParserConfig.java @@ -63,9 +63,6 @@ import com.alibaba.fastjson.asm.ASMException; import com.alibaba.fastjson.parser.deserializer.ASMDeserializerFactory; import com.alibaba.fastjson.parser.deserializer.ASMJavaBeanDeserializer; import com.alibaba.fastjson.parser.deserializer.ArrayDeserializer; -import com.alibaba.fastjson.parser.deserializer.ArrayListStringDeserializer; -import com.alibaba.fastjson.parser.deserializer.ArrayListStringFieldDeserializer; -import com.alibaba.fastjson.parser.deserializer.ArrayListTypeDeserializer; import com.alibaba.fastjson.parser.deserializer.ArrayListTypeFieldDeserializer; import com.alibaba.fastjson.parser.deserializer.AtomicIntegerArrayDeserializer; import com.alibaba.fastjson.parser.deserializer.AtomicLongArrayDeserializer; @@ -353,16 +350,7 @@ public class ParserConfig { return ArrayDeserializer.instance; } else if (clazz == Set.class || clazz == HashSet.class || clazz == Collection.class || clazz == List.class || clazz == ArrayList.class) { - if (type instanceof ParameterizedType) { - Type itemType = ((ParameterizedType) type).getActualTypeArguments()[0]; - if (itemType == String.class) { - derializer = ArrayListStringDeserializer.instance; - } else { - derializer = new ArrayListTypeDeserializer(clazz, itemType); - } - } else { - derializer = CollectionDeserializer.instance; - } + derializer = CollectionDeserializer.instance; } else if (Collection.class.isAssignableFrom(clazz)) { derializer = CollectionDeserializer.instance; } else if (Map.class.isAssignableFrom(clazz)) { @@ -500,14 +488,6 @@ public class ParserConfig { } if (fieldClass == List.class || fieldClass == ArrayList.class) { - Type fieldType = fieldInfo.getFieldType(); - if (fieldType instanceof ParameterizedType) { - Type itemType = ((ParameterizedType) fieldType).getActualTypeArguments()[0]; - if (itemType == String.class) { - return new ArrayListStringFieldDeserializer(mapping, clazz, fieldInfo); - } - } - return new ArrayListTypeFieldDeserializer(mapping, clazz, fieldInfo); } diff --git a/src/main/java/com/alibaba/fastjson/parser/deserializer/ArrayListStringDeserializer.java b/src/main/java/com/alibaba/fastjson/parser/deserializer/ArrayListStringDeserializer.java deleted file mode 100755 index f886a20b5..000000000 --- a/src/main/java/com/alibaba/fastjson/parser/deserializer/ArrayListStringDeserializer.java +++ /dev/null @@ -1,109 +0,0 @@ -package com.alibaba.fastjson.parser.deserializer; - -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashSet; -import java.util.Set; - -import com.alibaba.fastjson.JSONException; -import com.alibaba.fastjson.parser.DefaultJSONParser; -import com.alibaba.fastjson.parser.Feature; -import com.alibaba.fastjson.parser.JSONLexer; -import com.alibaba.fastjson.parser.JSONToken; - -public class ArrayListStringDeserializer implements ObjectDeserializer { - - public final static ArrayListStringDeserializer instance = new ArrayListStringDeserializer(); - - @SuppressWarnings({ "unchecked", "rawtypes" }) - public T deserialze(DefaultJSONParser parser, Type type, Object fieldName) { - - final JSONLexer lexer = parser.getLexer(); - if (lexer.token() == JSONToken.NULL) { - lexer.nextToken(JSONToken.COMMA); - return null; - } - - Collection array = null; - - if (type == Set.class || type == HashSet.class) { - array = new HashSet(); - } else { - if (type instanceof ParameterizedType) { - Type rawType = ((ParameterizedType) type).getRawType(); - if (rawType == Set.class || rawType == HashSet.class) { - array = new HashSet(); - } - } - } - - if (array == null) { - array = new ArrayList(); - } - - parseArray(parser, array); - - return (T) array; - } - - @SuppressWarnings({ "rawtypes", "unchecked" }) - public static void parseArray(DefaultJSONParser parser, Collection array) { - JSONLexer lexer = parser.getLexer(); - - if (lexer.token() == JSONToken.NULL) { - lexer.nextToken(JSONToken.COMMA); - return; - } - - if (lexer.token() == JSONToken.SET) { - lexer.nextToken(); - } - - if (lexer.token() != JSONToken.LBRACKET) { - throw new JSONException("exepct '[', but " + lexer.token()); - } - - lexer.nextToken(JSONToken.LITERAL_STRING); - - for (;;) { - if (lexer.isEnabled(Feature.AllowArbitraryCommas)) { - while (lexer.token() == JSONToken.COMMA) { - lexer.nextToken(); - continue; - } - } - - if (lexer.token() == JSONToken.RBRACKET) { - break; - } - - String value; - if (lexer.token() == JSONToken.LITERAL_STRING) { - value = lexer.stringVal(); - lexer.nextToken(JSONToken.COMMA); - } else { - Object obj = parser.parse(); - if (obj == null) { - value = null; - } else { - value = obj.toString(); - } - } - - array.add(value); - - if (lexer.token() == JSONToken.COMMA) { - lexer.nextToken(JSONToken.LITERAL_STRING); - continue; - } - } - - lexer.nextToken(JSONToken.COMMA); - } - - public int getFastMatchToken() { - return JSONToken.LBRACKET; - } -} diff --git a/src/main/java/com/alibaba/fastjson/parser/deserializer/ArrayListStringFieldDeserializer.java b/src/main/java/com/alibaba/fastjson/parser/deserializer/ArrayListStringFieldDeserializer.java deleted file mode 100755 index 50602ef38..000000000 --- a/src/main/java/com/alibaba/fastjson/parser/deserializer/ArrayListStringFieldDeserializer.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.alibaba.fastjson.parser.deserializer; - -import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.Map; - -import com.alibaba.fastjson.parser.DefaultJSONParser; -import com.alibaba.fastjson.parser.JSONLexer; -import com.alibaba.fastjson.parser.JSONToken; -import com.alibaba.fastjson.parser.ParserConfig; -import com.alibaba.fastjson.util.FieldInfo; - -public class ArrayListStringFieldDeserializer extends FieldDeserializer { - - public ArrayListStringFieldDeserializer(ParserConfig mapping, Class clazz, FieldInfo fieldInfo){ - super(clazz, fieldInfo); - - } - - public int getFastMatchToken() { - return JSONToken.LBRACKET; - } - - @Override - public void parseField(DefaultJSONParser parser, Object object, Type objectType, Map fieldValues) { - ArrayList list; - - final JSONLexer lexer = parser.getLexer(); - if (lexer.token() == JSONToken.NULL) { - lexer.nextToken(JSONToken.COMMA); - list = null; - } else { - list = new ArrayList(); - - ArrayListStringDeserializer.parseArray(parser, list); - } - if (object == null) { - fieldValues.put(fieldInfo.getName(), list); - } else { - setValue(object, list); - } - } -} diff --git a/src/main/java/com/alibaba/fastjson/parser/deserializer/ArrayListTypeDeserializer.java b/src/main/java/com/alibaba/fastjson/parser/deserializer/ArrayListTypeDeserializer.java deleted file mode 100755 index d151d847b..000000000 --- a/src/main/java/com/alibaba/fastjson/parser/deserializer/ArrayListTypeDeserializer.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.alibaba.fastjson.parser.deserializer; - -import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashSet; -import java.util.LinkedHashSet; - -import com.alibaba.fastjson.parser.DefaultJSONParser; -import com.alibaba.fastjson.parser.JSONToken; - -public class ArrayListTypeDeserializer implements ObjectDeserializer { - - private Type itemType; - private Class rawClass; - - public ArrayListTypeDeserializer(Class rawClass, Type itemType){ - this.rawClass = rawClass; - this.itemType = itemType; - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - public T deserialze(DefaultJSONParser parser, Type type, Object fieldName) { - Collection list = null; - - if (parser.getLexer().token() == JSONToken.NULL) { - parser.getLexer().nextToken(); - } else { - if (rawClass.isAssignableFrom(LinkedHashSet.class)) { - list = new LinkedHashSet(); - } else if (rawClass.isAssignableFrom(HashSet.class)) { - list = new HashSet(); - } else { - list = new ArrayList(); - } - - parser.parseArray(itemType, list, fieldName); - } - - return (T) list; - } - - public int getFastMatchToken() { - return JSONToken.LBRACKET; - } - -} diff --git a/src/main/java/com/alibaba/fastjson/parser/deserializer/DateFormatDeserializer.java b/src/main/java/com/alibaba/fastjson/parser/deserializer/DateFormatDeserializer.java index d5b089d65..f8f6a1ea7 100755 --- a/src/main/java/com/alibaba/fastjson/parser/deserializer/DateFormatDeserializer.java +++ b/src/main/java/com/alibaba/fastjson/parser/deserializer/DateFormatDeserializer.java @@ -13,6 +13,10 @@ public class DateFormatDeserializer extends AbstractDateDeserializer implements @SuppressWarnings("unchecked") protected T cast(DefaultJSONParser parser, Type clazz, Object fieldName, Object val) { + + if (val == null) { + return null; + } if (val instanceof String) { String strVal = (String) val; diff --git a/src/main/java/com/alibaba/fastjson/parser/deserializer/InetSocketAddressDeserializer.java b/src/main/java/com/alibaba/fastjson/parser/deserializer/InetSocketAddressDeserializer.java index d31377e09..b0034569d 100755 --- a/src/main/java/com/alibaba/fastjson/parser/deserializer/InetSocketAddressDeserializer.java +++ b/src/main/java/com/alibaba/fastjson/parser/deserializer/InetSocketAddressDeserializer.java @@ -27,8 +27,9 @@ public class InetSocketAddressDeserializer implements ObjectDeserializer { InetAddress address = null; int port = 0; for (;;) { - String key = lexer.symbol(parser.getSymbolTable()); - lexer.nextToken(); + String key = lexer.stringVal(); + lexer.nextToken(JSONToken.COLON); + if (key.equals("address")) { parser.accept(JSONToken.COLON); diff --git a/src/main/java/com/alibaba/fastjson/parser/deserializer/MapDeserializer.java b/src/main/java/com/alibaba/fastjson/parser/deserializer/MapDeserializer.java index 5d5b5435f..16f92a2f9 100755 --- a/src/main/java/com/alibaba/fastjson/parser/deserializer/MapDeserializer.java +++ b/src/main/java/com/alibaba/fastjson/parser/deserializer/MapDeserializer.java @@ -18,7 +18,6 @@ import com.alibaba.fastjson.parser.DefaultJSONParser; import com.alibaba.fastjson.parser.JSONLexer; import com.alibaba.fastjson.parser.JSONToken; import com.alibaba.fastjson.parser.ParseContext; -import com.alibaba.fastjson.util.AntiCollisionHashMap; public class MapDeserializer implements ObjectDeserializer { @@ -89,14 +88,10 @@ public class MapDeserializer implements ObjectDeserializer { return new ConcurrentHashMap(); } - if (type == Map.class ) { - return new AntiCollisionHashMap(); + if (type == Map.class || type == HashMap.class) { + return new HashMap(); } - if(type == HashMap.class){ // - return new HashMap(); - } - if (type == LinkedHashMap.class) { return new LinkedHashMap(); } diff --git a/src/main/java/com/alibaba/fastjson/serializer/ColorSerializer.java b/src/main/java/com/alibaba/fastjson/serializer/ColorSerializer.java index 0806a344b..a6a2be9c6 100755 --- a/src/main/java/com/alibaba/fastjson/serializer/ColorSerializer.java +++ b/src/main/java/com/alibaba/fastjson/serializer/ColorSerializer.java @@ -3,13 +3,10 @@ package com.alibaba.fastjson.serializer; import java.awt.Color; import java.io.IOException; import java.lang.reflect.Type; -import java.util.Collections; -import java.util.Set; import com.alibaba.fastjson.JSON; - -public class ColorSerializer implements AutowiredObjectSerializer { +public class ColorSerializer implements ObjectSerializer { public final static ColorSerializer instance = new ColorSerializer(); public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType) throws IOException { @@ -38,7 +35,4 @@ public class ColorSerializer implements AutowiredObjectSerializer { out.write('}'); } - public Set getAutowiredFor() { - return Collections.singleton(Color.class); - } } diff --git a/src/main/java/com/alibaba/fastjson/serializer/EnumerationSeriliazer.java b/src/main/java/com/alibaba/fastjson/serializer/EnumerationSeriliazer.java index 5f6b1c62b..4ec3e28b6 100755 --- a/src/main/java/com/alibaba/fastjson/serializer/EnumerationSeriliazer.java +++ b/src/main/java/com/alibaba/fastjson/serializer/EnumerationSeriliazer.java @@ -50,20 +50,6 @@ public class EnumerationSeriliazer implements ObjectSerializer { Class clazz = item.getClass(); - if (clazz == Integer.class) { - out.writeInt(((Integer) item).intValue()); - continue; - } - - if (clazz == Long.class) { - out.writeLong(((Long) item).longValue()); - - if (out.isEnabled(SerializerFeature.WriteClassName)) { - out.write('L'); - } - continue; - } - ObjectSerializer itemSerializer = serializer.getObjectWriter(clazz); itemSerializer.write(serializer, item, i - 1, elementType); } diff --git a/src/main/java/com/alibaba/fastjson/serializer/SerialContext.java b/src/main/java/com/alibaba/fastjson/serializer/SerialContext.java index 5c24bcdb3..6adf78ce4 100755 --- a/src/main/java/com/alibaba/fastjson/serializer/SerialContext.java +++ b/src/main/java/com/alibaba/fastjson/serializer/SerialContext.java @@ -8,22 +8,12 @@ public class SerialContext { private final Object fieldName; - private int features = 0; - public SerialContext(SerialContext parent, Object object, Object fieldName){ this.parent = parent; this.object = object; this.fieldName = fieldName; } - public int getFeatures() { - return features; - } - - public void setFeatures(int features) { - this.features = features; - } - public SerialContext getParent() { return parent; } diff --git a/src/main/java/com/alibaba/fastjson/support/spring/FastJsonJsonView.java b/src/main/java/com/alibaba/fastjson/support/spring/FastJsonJsonView.java index 08ec37f35..5aaa0285e 100755 --- a/src/main/java/com/alibaba/fastjson/support/spring/FastJsonJsonView.java +++ b/src/main/java/com/alibaba/fastjson/support/spring/FastJsonJsonView.java @@ -18,135 +18,133 @@ import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.serializer.SerializerFeature; /** - * * @author libinsong1204@gmail.com */ public class FastJsonJsonView extends AbstractView { - - public static final String DEFAULT_CONTENT_TYPE = "application/json"; - - public final static Charset UTF8 = Charset.forName("UTF-8"); - private Charset charset = UTF8; + public static final String DEFAULT_CONTENT_TYPE = "application/json"; - private SerializerFeature[] serializerFeature; - - private Set renderedAttributes; - - private boolean disableCaching = true; - - private boolean updateContentLength = false; + public final static Charset UTF8 = Charset.forName("UTF-8"); + + private Charset charset = UTF8; + + private SerializerFeature[] serializerFeatures = new SerializerFeature[0]; + + private Set renderedAttributes; + + private boolean disableCaching = true; + + private boolean updateContentLength = false; + + public FastJsonJsonView(){ + setContentType(DEFAULT_CONTENT_TYPE); + setExposePathVariables(false); + } + + public void setRenderedAttributes(Set renderedAttributes) { + this.renderedAttributes = renderedAttributes; + } + + @Deprecated + public void setSerializerFeature(SerializerFeature... features) { + this.setFeatures(features); + } - public FastJsonJsonView() { - setContentType(DEFAULT_CONTENT_TYPE); - setExposePathVariables(false); - } - - public void setRenderedAttributes(Set renderedAttributes) { - this.renderedAttributes = renderedAttributes; - } - - public void setSerializerFeature(SerializerFeature[] serializerFeature) { - this.serializerFeature = serializerFeature; - } - public Charset getCharset() { - return this.charset; - } - - public void setCharset(Charset charset) { - this.charset = charset; - } - - public SerializerFeature[] getFeatures() { - return serializerFeature; - } - - public void setFeatures(SerializerFeature... features) { - this.serializerFeature = features; + return this.charset; } - @Override - protected void renderMergedOutputModel(Map model, - HttpServletRequest request, HttpServletResponse response) - throws Exception { - Object value = filterModel(model); - - byte[] bytes; - if (charset == UTF8) { - if (serializerFeature != null) { - bytes = JSON.toJSONBytes(value, serializerFeature); + public void setCharset(Charset charset) { + this.charset = charset; + } + + public SerializerFeature[] getFeatures() { + return serializerFeatures; + } + + public void setFeatures(SerializerFeature... features) { + this.serializerFeatures = features; + } + + @Override + protected void renderMergedOutputModel(Map model, HttpServletRequest request, + HttpServletResponse response) throws Exception { + Object value = filterModel(model); + + byte[] bytes; + if (charset == UTF8) { + if (serializerFeatures != null) { + bytes = JSON.toJSONBytes(value, serializerFeatures); } else { bytes = JSON.toJSONBytes(value); } } else { String text; - if (serializerFeature != null) { - text = JSON.toJSONString(value, serializerFeature); + if (serializerFeatures != null) { + text = JSON.toJSONString(value, serializerFeatures); } else { text = JSON.toJSONString(value); } bytes = text.getBytes(charset); } - - OutputStream stream = this.updateContentLength ? createTemporaryOutputStream() : response.getOutputStream(); - stream.write(bytes); - - if (this.updateContentLength) { - writeToResponse(response, (ByteArrayOutputStream) stream); - } - } - - @Override - protected void prepareResponse(HttpServletRequest request, HttpServletResponse response) { - setResponseContentType(request, response); - response.setCharacterEncoding(UTF8.name()); - if (this.disableCaching) { - response.addHeader("Pragma", "no-cache"); - response.addHeader("Cache-Control", "no-cache, no-store, max-age=0"); - response.addDateHeader("Expires", 1L); - } - } - - /** - * Disables caching of the generated JSON. - *

Default is {@code true}, which will prevent the client from caching the generated JSON. - */ - public void setDisableCaching(boolean disableCaching) { - this.disableCaching = disableCaching; - } - /** - * Whether to update the 'Content-Length' header of the response. When set to - * {@code true}, the response is buffered in order to determine the content - * length and set the 'Content-Length' header of the response. - *

The default setting is {@code false}. - */ - public void setUpdateContentLength(boolean updateContentLength) { - this.updateContentLength = updateContentLength; - } - - - /** - * Filters out undesired attributes from the given model. The return value can be either another {@link Map}, or a - * single value object. - * - *

Default implementation removes {@link BindingResult} instances and entries not included in the {@link - * #setRenderedAttributes(Set) renderedAttributes} property. - * - * @param model the model, as passed on to {@link #renderMergedOutputModel} - * @return the object to be rendered - */ - protected Object filterModel(Map model) { - Map result = new HashMap(model.size()); - Set renderedAttributes = - !CollectionUtils.isEmpty(this.renderedAttributes) ? this.renderedAttributes : model.keySet(); - for (Map.Entry entry : model.entrySet()) { - if (!(entry.getValue() instanceof BindingResult) && renderedAttributes.contains(entry.getKey())) { - result.put(entry.getKey(), entry.getValue()); - } - } - return result; - } + OutputStream stream = this.updateContentLength ? createTemporaryOutputStream() : response.getOutputStream(); + stream.write(bytes); -} \ No newline at end of file + if (this.updateContentLength) { + writeToResponse(response, (ByteArrayOutputStream) stream); + } + } + + @Override + protected void prepareResponse(HttpServletRequest request, HttpServletResponse response) { + setResponseContentType(request, response); + response.setCharacterEncoding(UTF8.name()); + if (this.disableCaching) { + response.addHeader("Pragma", "no-cache"); + response.addHeader("Cache-Control", "no-cache, no-store, max-age=0"); + response.addDateHeader("Expires", 1L); + } + } + + /** + * Disables caching of the generated JSON. + *

+ * Default is {@code true}, which will prevent the client from caching the generated JSON. + */ + public void setDisableCaching(boolean disableCaching) { + this.disableCaching = disableCaching; + } + + /** + * Whether to update the 'Content-Length' header of the response. When set to {@code true}, the response is buffered + * in order to determine the content length and set the 'Content-Length' header of the response. + *

+ * The default setting is {@code false}. + */ + public void setUpdateContentLength(boolean updateContentLength) { + this.updateContentLength = updateContentLength; + } + + /** + * Filters out undesired attributes from the given model. The return value can be either another {@link Map}, or a + * single value object. + *

+ * Default implementation removes {@link BindingResult} instances and entries not included in the + * {@link #setRenderedAttributes(Set) renderedAttributes} property. + * + * @param model the model, as passed on to {@link #renderMergedOutputModel} + * @return the object to be rendered + */ + protected Object filterModel(Map model) { + Map result = new HashMap(model.size()); + Set renderedAttributes = !CollectionUtils.isEmpty(this.renderedAttributes) ? this.renderedAttributes : model.keySet(); + for (Map.Entry entry : model.entrySet()) { + if (!(entry.getValue() instanceof BindingResult) && renderedAttributes.contains(entry.getKey())) { + result.put(entry.getKey(), entry.getValue()); + } + } + return result; + } + +} diff --git a/src/main/java/com/alibaba/fastjson/util/AntiCollisionHashMap.java b/src/main/java/com/alibaba/fastjson/util/AntiCollisionHashMap.java deleted file mode 100755 index 908ddb203..000000000 --- a/src/main/java/com/alibaba/fastjson/util/AntiCollisionHashMap.java +++ /dev/null @@ -1,1117 +0,0 @@ -package com.alibaba.fastjson.util; - -/* - * %W% %E% - * - * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. - * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - */ - -import java.io.IOException; -import java.io.Serializable; -import java.util.AbstractCollection; -import java.util.AbstractMap; -import java.util.AbstractSet; -import java.util.Collection; -import java.util.Collections; -import java.util.ConcurrentModificationException; -import java.util.Hashtable; -import java.util.Iterator; -import java.util.Map; -import java.util.NoSuchElementException; -import java.util.Random; -import java.util.Set; -import java.util.TreeMap; - -/** - * This class modfiy from jdk src. - * - * Hash table based implementation of the Map interface. This - * implementation provides all of the optional map operations, and permits - * null values and the null key. (The SafelyHashMap - * class is roughly equivalent to Hashtable, except that it is - * unsynchronized and permits nulls.) This class makes no guarantees as to the - * order of the map; in particular, it does not guarantee that the order will - * remain constant over time. - * - *

- * This implementation provides constant-time performance for the basic - * operations (get and put), assuming the hash function - * disperses the elements properly among the buckets. Iteration over collection - * views requires time proportional to the "capacity" of the - * SafelyHashMap instance (the number of buckets) plus its size (the - * number of key-value mappings). Thus, it's very important not to set the - * initial capacity too high (or the load factor too low) if iteration - * performance is important. - * - *

- * An instance of SafelyHashMap has two parameters that affect its - * performance: initial capacity and load factor. The - * capacity is the number of buckets in the hash table, and the initial - * capacity is simply the capacity at the time the hash table is created. The - * load factor is a measure of how full the hash table is allowed to get - * before its capacity is automatically increased. When the number of entries in - * the hash table exceeds the product of the load factor and the current - * capacity, the hash table is rehashed (that is, internal data - * structures are rebuilt) so that the hash table has approximately twice the - * number of buckets. - * - *

- * As a general rule, the default load factor (.75) offers a good tradeoff - * between time and space costs. Higher values decrease the space overhead but - * increase the lookup cost (reflected in most of the operations of the - * SafelyHashMap class, including get and put). The - * expected number of entries in the map and its load factor should be taken - * into account when setting its initial capacity, so as to minimize the number - * of rehash operations. If the initial capacity is greater than the maximum - * number of entries divided by the load factor, no rehash operations will ever - * occur. - * - *

- * If many mappings are to be stored in a SafelyHashMap instance, - * creating it with a sufficiently large capacity will allow the mappings to be - * stored more efficiently than letting it perform automatic rehashing as needed - * to grow the table. - * - *

- * Note that this implementation is not synchronized. If - * multiple threads access a hash map concurrently, and at least one of the - * threads modifies the map structurally, it must be synchronized - * externally. (A structural modification is any operation that adds or deletes - * one or more mappings; merely changing the value associated with a key that an - * instance already contains is not a structural modification.) This is - * typically accomplished by synchronizing on some object that naturally - * encapsulates the map. - * - * If no such object exists, the map should be "wrapped" using the - * {@link Collections#synchronizedMap Collections.synchronizedMap} method. This - * is best done at creation time, to prevent accidental unsynchronized access to - * the map: - * - *

- *   Map m = Collections.synchronizedMap(new SafelyHashMap(...));
- * 
- * - *

- * The iterators returned by all of this class's "collection view methods" are - * fail-fast: if the map is structurally modified at any time after the - * iterator is created, in any way except through the iterator's own - * remove method, the iterator will throw a - * {@link ConcurrentModificationException}. Thus, in the face of concurrent - * modification, the iterator fails quickly and cleanly, rather than risking - * arbitrary, non-deterministic behavior at an undetermined time in the future. - * - *

- * Note that the fail-fast behavior of an iterator cannot be guaranteed as it - * is, generally speaking, impossible to make any hard guarantees in the - * presence of unsynchronized concurrent modification. Fail-fast iterators throw - * ConcurrentModificationException on a best-effort basis. Therefore, - * it would be wrong to write a program that depended on this exception for its - * correctness: the fail-fast behavior of iterators should be used only to - * detect bugs. - * - *

- * This class is a member of the Java Collections Framework. - * - * @param - * the type of keys maintained by this map - * @param - * the type of mapped values - * - * @author Axman - * @author Doug Lea - * @author Josh Bloch - * @author Arthur van Hoff - * @author Neal Gafter - * @version %I%, %G% - * @see Object#hashCode() - * @see Collection - * @see Map - * @see TreeMap - * @see Hashtable - */ -@SuppressWarnings({"unchecked", "rawtypes"}) -public class AntiCollisionHashMap extends AbstractMap implements - Map, Cloneable, Serializable { - - transient volatile Set keySet = null; - transient volatile Collection values = null; - - /** - * The default initial capacity - MUST be a power of two. - */ - static final int DEFAULT_INITIAL_CAPACITY = 16; - - /** - * The maximum capacity, used if a higher value is implicitly specified by - * either of the constructors with arguments. MUST be a power of two <= - * 1<<30. - */ - static final int MAXIMUM_CAPACITY = 1 << 30; - - /** - * The load factor used when none specified in constructor. - */ - static final float DEFAULT_LOAD_FACTOR = 0.75f; - - /** - * The table, resized as necessary. Length MUST Always be a power of two. - */ - transient Entry[] table; - - /** - * The number of key-value mappings contained in this map. - */ - transient int size; - - /** - * The next size value at which to resize (capacity * load factor). - * - * @serial - */ - int threshold; - - /** - * The load factor for the hash table. - * - * @serial - */ - final float loadFactor; - - /** - * The number of times this SafelyHashMap has been structurally modified - * Structural modifications are those that change the number of mappings in - * the SafelyHashMap or otherwise modify its internal structure (e.g., - * rehash). This field is used to make iterators on Collection-views of the - * SafelyHashMap fail-fast. (See ConcurrentModificationException). - */ - transient volatile int modCount; - - /** - * Constructs an empty SafelyHashMap with the specified initial - * capacity and load factor. - * - * @param initialCapacity - * the initial capacity - * @param loadFactor - * the load factor - * @throws IllegalArgumentException - * if the initial capacity is negative or the load factor is - * nonpositive - */ - - final static int M_MASK = 0x8765fed3; - final static int SEED = -2128831035; - final static int KEY = 16777619; - - final int random = new Random().nextInt(99999); // a fixed value in an instance - private int hashString(String key) { - - int hash = SEED * random; - for (int i = 0; i < key.length(); i++) - hash = (hash * KEY) ^ key.charAt(i); - return (hash ^ (hash >> 1)) & M_MASK; - } - - public AntiCollisionHashMap(int initialCapacity, float loadFactor) { - if (initialCapacity < 0) - throw new IllegalArgumentException("Illegal initial capacity: " - + initialCapacity); - if (initialCapacity > MAXIMUM_CAPACITY) - initialCapacity = MAXIMUM_CAPACITY; - if (loadFactor <= 0 || Float.isNaN(loadFactor)) - throw new IllegalArgumentException("Illegal load factor: " - + loadFactor); - - // Find a power of 2 >= initialCapacity - int capacity = 1; - while (capacity < initialCapacity) - capacity <<= 1; - - this.loadFactor = loadFactor; - threshold = (int) (capacity * loadFactor); - table = new Entry[capacity]; - init(); - } - - /** - * Constructs an empty SafelyHashMap with the specified initial - * capacity and the default load factor (0.75). - * - * @param initialCapacity - * the initial capacity. - * @throws IllegalArgumentException - * if the initial capacity is negative. - */ - public AntiCollisionHashMap(int initialCapacity) { - this(initialCapacity, DEFAULT_LOAD_FACTOR); - } - - /** - * Constructs an empty SafelyHashMap with the default initial - * capacity (16) and the default load factor (0.75). - */ - public AntiCollisionHashMap() { - this.loadFactor = DEFAULT_LOAD_FACTOR; - threshold = (int) (DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR); - table = new Entry[DEFAULT_INITIAL_CAPACITY]; - init(); - } - - /** - * Constructs a new SafelyHashMap with the same mappings as the - * specified Map. The SafelyHashMap is created with - * default load factor (0.75) and an initial capacity sufficient to hold the - * mappings in the specified Map. - * - * @param m - * the map whose mappings are to be placed in this map - * @throws NullPointerException - * if the specified map is null - */ - public AntiCollisionHashMap(Map m) { - this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1, - DEFAULT_INITIAL_CAPACITY), DEFAULT_LOAD_FACTOR); - putAllForCreate(m); - } - - // internal utilities - - /** - * Initialization hook for subclasses. This method is called in all - * constructors and pseudo-constructors (clone, readObject) after - * SafelyHashMap has been initialized but before any entries have been - * inserted. (In the absence of this method, readObject would require - * explicit knowledge of subclasses.) - */ - void init() { - } - - /** - * Applies a supplemental hash function to a given hashCode, which defends - * against poor quality hash functions. This is critical because - * SafelyHashMap uses power-of-two length hash tables, that otherwise - * encounter collisions for hashCodes that do not differ in lower bits. - * Note: Null keys always map to hash 0, thus index 0. - */ - static int hash(int h) { - // This function ensures that hashCodes that differ only by - // constant multiples at each bit position have a bounded - // number of collisions (approximately 8 at default load factor). - h = h * h; - h ^= (h >>> 20) ^ (h >>> 12); - return h ^ (h >>> 7) ^ (h >>> 4); - } - - /** - * Returns index for hash code h. - */ - static int indexFor(int h, int length) { - return h & (length - 1); - } - - /** - * Returns the number of key-value mappings in this map. - * - * @return the number of key-value mappings in this map - */ - public int size() { - return size; - } - - /** - * Returns true if this map contains no key-value mappings. - * - * @return true if this map contains no key-value mappings - */ - public boolean isEmpty() { - return size == 0; - } - - /** - * Returns the value to which the specified key is mapped, or {@code null} - * if this map contains no mapping for the key. - * - *

- * More formally, if this map contains a mapping from a key {@code k} to a - * value {@code v} such that {@code (key==null ? k==null : - * key.equals(k))}, then this method returns {@code v}; otherwise it returns - * {@code null}. (There can be at most one such mapping.) - * - *

- * A return value of {@code null} does not necessarily indicate that - * the map contains no mapping for the key; it's also possible that the map - * explicitly maps the key to {@code null}. The {@link #containsKey - * containsKey} operation may be used to distinguish these two cases. - * - * @see #put(Object, Object) - */ - public V get(Object key) { - if (key == null) - return getForNullKey(); - int hash = 0; - if (key instanceof String) - hash = hash(hashString((String) key)); - else - hash = hash(key.hashCode()); - for (Entry e = table[indexFor(hash, table.length)]; e != null; e = e.next) { - Object k; - if (e.hash == hash && ((k = e.key) == key || key.equals(k))) - return e.value; - } - return null; - } - - /** - * Offloaded version of get() to look up null keys. Null keys map to index - * 0. This null case is split out into separate methods for the sake of - * performance in the two most commonly used operations (get and put), but - * incorporated with conditionals in others. - */ - private V getForNullKey() { - for (Entry e = table[0]; e != null; e = e.next) { - if (e.key == null) - return e.value; - } - return null; - } - - /** - * Returns true if this map contains a mapping for the specified - * key. - * - * @param key - * The key whose presence in this map is to be tested - * @return true if this map contains a mapping for the specified - * key. - */ - public boolean containsKey(Object key) { - return getEntry(key) != null; - } - - /** - * Returns the entry associated with the specified key in the SafelyHashMap. - * Returns null if the SafelyHashMap contains no mapping for the key. - */ - final Entry getEntry(Object key) { - int hash = (key == null) ? 0 - : (key instanceof String) ? hash(hashString((String) key)) - : hash(key.hashCode()); - for (Entry e = table[indexFor(hash, table.length)]; e != null; e = e.next) { - Object k; - if (e.hash == hash - && ((k = e.key) == key || (key != null && key.equals(k)))) - return e; - } - return null; - } - - /** - * Associates the specified value with the specified key in this map. If the - * map previously contained a mapping for the key, the old value is - * replaced. - * - * @param key - * key with which the specified value is to be associated - * @param value - * value to be associated with the specified key - * @return the previous value associated with key, or null - * if there was no mapping for key. (A null return - * can also indicate that the map previously associated - * null with key.) - */ - public V put(K key, V value) { - if (key == null) - return putForNullKey(value); - int hash = 0; - if (key instanceof String) - hash = hash(hashString((String) key)); - else - hash = hash(key.hashCode()); - int i = indexFor(hash, table.length); - for (Entry e = table[i]; e != null; e = e.next) { - Object k; - if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { - V oldValue = e.value; - e.value = value; - e.recordAccess(this); - return oldValue; - } - } - - modCount++; - addEntry(hash, key, value, i); - return null; - } - - /** - * Offloaded version of put for null keys - */ - private V putForNullKey(V value) { - for (Entry e = table[0]; e != null; e = e.next) { - if (e.key == null) { - V oldValue = e.value; - e.value = value; - e.recordAccess(this); - return oldValue; - } - } - modCount++; - addEntry(0, null, value, 0); - return null; - } - - /** - * This method is used instead of put by constructors and pseudoconstructors - * (clone, readObject). It does not resize the table, check for - * comodification, etc. It calls createEntry rather than addEntry. - */ - private void putForCreate(K key, V value) { - int hash = (key == null) ? 0 - : (key instanceof String) ? hash(hashString((String) key)) - : hash(key.hashCode()); - int i = indexFor(hash, table.length); - - /** - * Look for preexisting entry for key. This will never happen for clone - * or deserialize. It will only happen for construction if the input Map - * is a sorted map whose ordering is inconsistent w/ equals. - */ - for (Entry e = table[i]; e != null; e = e.next) { - Object k; - if (e.hash == hash - && ((k = e.key) == key || (key != null && key.equals(k)))) { - e.value = value; - return; - } - } - - createEntry(hash, key, value, i); - } - - private void putAllForCreate(Map m) { - for (Iterator> i = m - .entrySet().iterator(); i.hasNext();) { - Map.Entry e = i.next(); - putForCreate(e.getKey(), e.getValue()); - } - } - - /** - * Rehashes the contents of this map into a new array with a larger - * capacity. This method is called automatically when the number of keys in - * this map reaches its threshold. - * - * If current capacity is MAXIMUM_CAPACITY, this method does not resize the - * map, but sets threshold to Integer.MAX_VALUE. This has the effect of - * preventing future calls. - * - * @param newCapacity - * the new capacity, MUST be a power of two; must be greater than - * current capacity unless current capacity is MAXIMUM_CAPACITY - * (in which case value is irrelevant). - */ - void resize(int newCapacity) { - Entry[] oldTable = table; - int oldCapacity = oldTable.length; - if (oldCapacity == MAXIMUM_CAPACITY) { - threshold = Integer.MAX_VALUE; - return; - } - - Entry[] newTable = new Entry[newCapacity]; - transfer(newTable); - table = newTable; - threshold = (int) (newCapacity * loadFactor); - } - - /** - * Transfers all entries from current table to newTable. - */ - void transfer(Entry[] newTable) { - Entry[] src = table; - int newCapacity = newTable.length; - for (int j = 0; j < src.length; j++) { - Entry e = src[j]; - if (e != null) { - src[j] = null; - do { - Entry next = e.next; - int i = indexFor(e.hash, newCapacity); - e.next = newTable[i]; - newTable[i] = e; - e = next; - } while (e != null); - } - } - } - - /** - * Copies all of the mappings from the specified map to this map. These - * mappings will replace any mappings that this map had for any of the keys - * currently in the specified map. - * - * @param m - * mappings to be stored in this map - * @throws NullPointerException - * if the specified map is null - */ - public void putAll(Map m) { - int numKeysToBeAdded = m.size(); - if (numKeysToBeAdded == 0) - return; - - /* - * Expand the map if the map if the number of mappings to be added is - * greater than or equal to threshold. This is conservative; the obvious - * condition is (m.size() + size) >= threshold, but this condition could - * result in a map with twice the appropriate capacity, if the keys to - * be added overlap with the keys already in this map. By using the - * conservative calculation, we subject ourself to at most one extra - * resize. - */ - if (numKeysToBeAdded > threshold) { - int targetCapacity = (int) (numKeysToBeAdded / loadFactor + 1); - if (targetCapacity > MAXIMUM_CAPACITY) - targetCapacity = MAXIMUM_CAPACITY; - int newCapacity = table.length; - while (newCapacity < targetCapacity) - newCapacity <<= 1; - if (newCapacity > table.length) - resize(newCapacity); - } - - for (Iterator> i = m - .entrySet().iterator(); i.hasNext();) { - Map.Entry e = i.next(); - put(e.getKey(), e.getValue()); - } - } - - /** - * Removes the mapping for the specified key from this map if present. - * - * @param key - * key whose mapping is to be removed from the map - * @return the previous value associated with key, or null - * if there was no mapping for key. (A null return - * can also indicate that the map previously associated - * null with key.) - */ - public V remove(Object key) { - Entry e = removeEntryForKey(key); - return (e == null ? null : e.value); - } - - /** - * Removes and returns the entry associated with the specified key in the - * SafelyHashMap. Returns null if the SafelyHashMap contains no mapping for - * this key. - */ - final Entry removeEntryForKey(Object key) { - int hash = (key == null) ? 0 - : (key instanceof String) ? hash(hashString((String) key)) - : hash(key.hashCode()); - int i = indexFor(hash, table.length); - Entry prev = table[i]; - Entry e = prev; - - while (e != null) { - Entry next = e.next; - Object k; - if (e.hash == hash - && ((k = e.key) == key || (key != null && key.equals(k)))) { - modCount++; - size--; - if (prev == e) - table[i] = next; - else - prev.next = next; - e.recordRemoval(this); - return e; - } - prev = e; - e = next; - } - - return e; - } - - /** - * Special version of remove for EntrySet. - */ - final Entry removeMapping(Object o) { - if (!(o instanceof Map.Entry)) - return null; - - Map.Entry entry = (Map.Entry) o; - Object key = entry.getKey(); - int hash = (key == null) ? 0 - : (key instanceof String) ? hash(hashString((String) key)) - : hash(key.hashCode()); - int i = indexFor(hash, table.length); - Entry prev = table[i]; - Entry e = prev; - - while (e != null) { - Entry next = e.next; - if (e.hash == hash && e.equals(entry)) { - modCount++; - size--; - if (prev == e) - table[i] = next; - else - prev.next = next; - e.recordRemoval(this); - return e; - } - prev = e; - e = next; - } - - return e; - } - - /** - * Removes all of the mappings from this map. The map will be empty after - * this call returns. - */ - public void clear() { - modCount++; - Entry[] tab = table; - for (int i = 0; i < tab.length; i++) - tab[i] = null; - size = 0; - } - - /** - * Returns true if this map maps one or more keys to the specified - * value. - * - * @param value - * value whose presence in this map is to be tested - * @return true if this map maps one or more keys to the specified - * value - */ - public boolean containsValue(Object value) { - if (value == null) - return containsNullValue(); - - Entry[] tab = table; - for (int i = 0; i < tab.length; i++) - for (Entry e = tab[i]; e != null; e = e.next) - if (value.equals(e.value)) - return true; - return false; - } - - /** - * Special-case code for containsValue with null argument - */ - private boolean containsNullValue() { - Entry[] tab = table; - for (int i = 0; i < tab.length; i++) - for (Entry e = tab[i]; e != null; e = e.next) - if (e.value == null) - return true; - return false; - } - - /** - * Returns a shallow copy of this SafelyHashMap instance: the keys - * and values themselves are not cloned. - * - * @return a shallow copy of this map - */ - public Object clone() { - AntiCollisionHashMap result = null; - try { - result = (AntiCollisionHashMap) super.clone(); - } catch (CloneNotSupportedException e) { - // assert false; - } - result.table = new Entry[table.length]; - result.entrySet = null; - result.modCount = 0; - result.size = 0; - result.init(); - result.putAllForCreate(this); - - return result; - } - - static class Entry implements Map.Entry { - final K key; - V value; - Entry next; - final int hash; - - /** - * Creates new entry. - */ - Entry(int h, K k, V v, Entry n) { - value = v; - next = n; - key = k; - hash = h; - } - - public final K getKey() { - return key; - } - - public final V getValue() { - return value; - } - - public final V setValue(V newValue) { - V oldValue = value; - value = newValue; - return oldValue; - } - - public final boolean equals(Object o) { - if (!(o instanceof Map.Entry)) - return false; - Map.Entry e = (Map.Entry) o; - Object k1 = getKey(); - Object k2 = e.getKey(); - if (k1 == k2 || (k1 != null && k1.equals(k2))) { - Object v1 = getValue(); - Object v2 = e.getValue(); - if (v1 == v2 || (v1 != null && v1.equals(v2))) - return true; - } - return false; - } - - public final int hashCode() { - return (key == null ? 0 : key.hashCode()) - ^ (value == null ? 0 : value.hashCode()); - } - - public final String toString() { - return getKey() + "=" + getValue(); - } - - /** - * This method is invoked whenever the value in an entry is overwritten - * by an invocation of put(k,v) for a key k that's already in the - * SafelyHashMap. - */ - void recordAccess(AntiCollisionHashMap m) { - } - - /** - * This method is invoked whenever the entry is removed from the table. - */ - void recordRemoval(AntiCollisionHashMap m) { - } - } - - /** - * Adds a new entry with the specified key, value and hash code to the - * specified bucket. It is the responsibility of this method to resize the - * table if appropriate. - * - * Subclass overrides this to alter the behavior of put method. - */ - void addEntry(int hash, K key, V value, int bucketIndex) { - Entry e = table[bucketIndex]; - table[bucketIndex] = new Entry(hash, key, value, e); - if (size++ >= threshold) - resize(2 * table.length); - } - - /** - * Like addEntry except that this version is used when creating entries as - * part of Map construction or "pseudo-construction" (cloning, - * deserialization). This version needn't worry about resizing the table. - * - * Subclass overrides this to alter the behavior of SafelyHashMap(Map), - * clone, and readObject. - */ - void createEntry(int hash, K key, V value, int bucketIndex) { - Entry e = table[bucketIndex]; - table[bucketIndex] = new Entry(hash, key, value, e); - size++; - } - - private abstract class HashIterator implements Iterator { - Entry next; // next entry to return - int expectedModCount; // For fast-fail - int index; // current slot - Entry current; // current entry - - HashIterator() { - expectedModCount = modCount; - if (size > 0) { // advance to first entry - Entry[] t = table; - while (index < t.length && (next = t[index++]) == null) - ; - } - } - - public final boolean hasNext() { - return next != null; - } - - final Entry nextEntry() { - if (modCount != expectedModCount) - throw new ConcurrentModificationException(); - Entry e = next; - if (e == null) - throw new NoSuchElementException(); - - if ((next = e.next) == null) { - Entry[] t = table; - while (index < t.length && (next = t[index++]) == null) - ; - } - current = e; - return e; - } - - public void remove() { - if (current == null) - throw new IllegalStateException(); - if (modCount != expectedModCount) - throw new ConcurrentModificationException(); - Object k = current.key; - current = null; - AntiCollisionHashMap.this.removeEntryForKey(k); - expectedModCount = modCount; - } - - } - - private final class ValueIterator extends HashIterator { - public V next() { - return nextEntry().value; - } - } - - private final class KeyIterator extends HashIterator { - public K next() { - return nextEntry().getKey(); - } - } - - private final class EntryIterator extends HashIterator> { - public Map.Entry next() { - return nextEntry(); - } - } - - // Subclass overrides these to alter behavior of views' iterator() method - Iterator newKeyIterator() { - return new KeyIterator(); - } - - Iterator newValueIterator() { - return new ValueIterator(); - } - - Iterator> newEntryIterator() { - return new EntryIterator(); - } - - // Views - - private transient Set> entrySet = null; - - /** - * Returns a {@link Set} view of the keys contained in this map. The set is - * backed by the map, so changes to the map are reflected in the set, and - * vice-versa. If the map is modified while an iteration over the set is in - * progress (except through the iterator's own remove operation), - * the results of the iteration are undefined. The set supports element - * removal, which removes the corresponding mapping from the map, via the - * Iterator.remove, Set.remove, removeAll, - * retainAll, and clear operations. It does not support - * the add or addAll operations. - */ - public Set keySet() { - - Set ks = keySet; - return (ks != null ? ks : (keySet = new KeySet())); - } - - private final class KeySet extends AbstractSet { - public Iterator iterator() { - return newKeyIterator(); - } - - public int size() { - return size; - } - - public boolean contains(Object o) { - return containsKey(o); - } - - public boolean remove(Object o) { - return AntiCollisionHashMap.this.removeEntryForKey(o) != null; - } - - public void clear() { - AntiCollisionHashMap.this.clear(); - } - } - - /** - * Returns a {@link Collection} view of the values contained in this map. - * The collection is backed by the map, so changes to the map are reflected - * in the collection, and vice-versa. If the map is modified while an - * iteration over the collection is in progress (except through the - * iterator's own remove operation), the results of the iteration - * are undefined. The collection supports element removal, which removes the - * corresponding mapping from the map, via the Iterator.remove, - * Collection.remove, removeAll, retainAll and - * clear operations. It does not support the add or - * addAll operations. - */ - public Collection values() { - Collection vs = values; - return (vs != null ? vs : (values = new Values())); - } - - private final class Values extends AbstractCollection { - public Iterator iterator() { - return newValueIterator(); - } - - public int size() { - return size; - } - - public boolean contains(Object o) { - return containsValue(o); - } - - public void clear() { - AntiCollisionHashMap.this.clear(); - } - } - - /** - * Returns a {@link Set} view of the mappings contained in this map. The set - * is backed by the map, so changes to the map are reflected in the set, and - * vice-versa. If the map is modified while an iteration over the set is in - * progress (except through the iterator's own remove operation, or - * through the setValue operation on a map entry returned by the - * iterator) the results of the iteration are undefined. The set supports - * element removal, which removes the corresponding mapping from the map, - * via the Iterator.remove, Set.remove, removeAll - * , retainAll and clear operations. It does not support - * the add or addAll operations. - * - * @return a set view of the mappings contained in this map - */ - public Set> entrySet() { - return entrySet0(); - } - - private Set> entrySet0() { - Set> es = entrySet; - return es != null ? es : (entrySet = new EntrySet()); - } - - private final class EntrySet extends AbstractSet> { - public Iterator> iterator() { - return newEntryIterator(); - } - - public boolean contains(Object o) { - if (!(o instanceof Map.Entry)) - return false; - Map.Entry e = (Map.Entry) o; - Entry candidate = getEntry(e.getKey()); - return candidate != null && candidate.equals(e); - } - - public boolean remove(Object o) { - return removeMapping(o) != null; - } - - public int size() { - return size; - } - - public void clear() { - AntiCollisionHashMap.this.clear(); - } - } - - /** - * Save the state of the SafelyHashMap instance to a stream (i.e., - * serialize it). - * - * @serialData The capacity of the SafelyHashMap (the length of the - * bucket array) is emitted (int), followed by the size - * (an int, the number of key-value mappings), followed by the - * key (Object) and value (Object) for each key-value mapping. - * The key-value mappings are emitted in no particular order. - */ - private void writeObject(java.io.ObjectOutputStream s) throws IOException { - Iterator> i = (size > 0) ? entrySet0().iterator() - : null; - - // Write out the threshold, loadfactor, and any hidden stuff - s.defaultWriteObject(); - - // Write out number of buckets - s.writeInt(table.length); - - // Write out size (number of Mappings) - s.writeInt(size); - - // Write out keys and values (alternating) - if (i != null) { - while (i.hasNext()) { - Map.Entry e = i.next(); - s.writeObject(e.getKey()); - s.writeObject(e.getValue()); - } - } - } - - private static final long serialVersionUID = 362498820763181265L; - - /** - * Reconstitute the SafelyHashMap instance from a stream (i.e., - * deserialize it). - */ - private void readObject(java.io.ObjectInputStream s) throws IOException, - ClassNotFoundException { - // Read in the threshold, loadfactor, and any hidden stuff - s.defaultReadObject(); - - // Read in number of buckets and allocate the bucket array; - int numBuckets = s.readInt(); - table = new Entry[numBuckets]; - - init(); // Give subclass a chance to do its thing. - - // Read in size (number of Mappings) - int size = s.readInt(); - - // Read the keys and values, and put the mappings in the SafelyHashMap - for (int i = 0; i < size; i++) { - K key = (K) s.readObject(); - V value = (V) s.readObject(); - putForCreate(key, value); - } - } - - // These methods are used when serializing HashSets - int capacity() { - return table.length; - } - - float loadFactor() { - return loadFactor; - } - -} diff --git a/src/main/java/com/alibaba/fastjson/util/ParameterizedTypeImpl.java b/src/main/java/com/alibaba/fastjson/util/ParameterizedTypeImpl.java index b7d4f1fd0..a5cb33fcd 100755 --- a/src/main/java/com/alibaba/fastjson/util/ParameterizedTypeImpl.java +++ b/src/main/java/com/alibaba/fastjson/util/ParameterizedTypeImpl.java @@ -2,75 +2,29 @@ package com.alibaba.fastjson.util; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; -import java.util.Arrays; public class ParameterizedTypeImpl implements ParameterizedType { - private final Type[] actualTypeArguments; - private final Type ownerType; - private final Type rawType; - private int hash; - public ParameterizedTypeImpl(Type[] actualTypeArguments, Type ownerType, - Type rawType) { - super(); - if (actualTypeArguments == null || actualTypeArguments.length == 0 - || rawType == null) - throw new IllegalArgumentException(); - this.actualTypeArguments = actualTypeArguments; - this.ownerType = ownerType; - this.rawType = rawType; + private final Type[] actualTypeArguments; + private final Type ownerType; + private final Type rawType; - hash = 31 + (ownerType != null ? ownerType.hashCode() : 0); - hash = 31 * hash + rawType.hashCode(); - hash = 31 * hash + Arrays.hashCode(actualTypeArguments); - } + public ParameterizedTypeImpl(Type[] actualTypeArguments, Type ownerType, Type rawType){ + this.actualTypeArguments = actualTypeArguments; + this.ownerType = ownerType; + this.rawType = rawType; + } - public Type[] getActualTypeArguments() { - return actualTypeArguments; - } + public Type[] getActualTypeArguments() { + return actualTypeArguments; + } - public Type getOwnerType() { - return ownerType; - } + public Type getOwnerType() { + return ownerType; + } - public Type getRawType() { - return rawType; - } + public Type getRawType() { + return rawType; + } - @Override - public int hashCode() { - return hash; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (!(obj instanceof ParameterizedType)) { - return false; - } - ParameterizedType other = (ParameterizedType) obj; - if (!Arrays.equals(actualTypeArguments, other.getActualTypeArguments())) { - return false; - } - if (ownerType == null) { - if (other.getOwnerType() != null) { - return false; - } - } else if (!ownerType.equals(other.getOwnerType())) { - return false; - } - if (rawType == null) { - if (other.getRawType() != null) { - return false; - } - } else if (!rawType.equals(other.getRawType())) { - return false; - } - return true; - } } diff --git a/src/main/java/com/alibaba/fastjson/util/ServiceLoader.java b/src/main/java/com/alibaba/fastjson/util/ServiceLoader.java index 053f49d61..5051ca051 100755 --- a/src/main/java/com/alibaba/fastjson/util/ServiceLoader.java +++ b/src/main/java/com/alibaba/fastjson/util/ServiceLoader.java @@ -1,7 +1,6 @@ package com.alibaba.fastjson.util; import java.io.BufferedReader; -import java.io.Closeable; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -12,8 +11,8 @@ import java.util.Set; public class ServiceLoader { - private static final String PREFIX = "META-INF/services/"; - + private static final String PREFIX = "META-INF/services/"; + private static final Set loadedUrls = new HashSet(); @SuppressWarnings("unchecked") @@ -75,15 +74,8 @@ public class ServiceLoader { set.add(line); } } finally { - close(reader); - close(is); + IOUtils.close(reader); + IOUtils.close(is); } } - - public static void close(Closeable x) throws IOException { - if (x != null) { - x.close(); - } - } - } diff --git a/src/test/java/com/alibaba/json/bvt/parser/AnticollisionHashMapTest.java b/src/test/java/com/alibaba/json/bvt/parser/AnticollisionHashMapTest.java deleted file mode 100755 index 0976add48..000000000 --- a/src/test/java/com/alibaba/json/bvt/parser/AnticollisionHashMapTest.java +++ /dev/null @@ -1,78 +0,0 @@ -package com.alibaba.json.bvt.parser; - -import java.io.BufferedReader; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.util.Map; - -import junit.framework.TestCase; - -import com.alibaba.fastjson.util.AntiCollisionHashMap; - -public class AnticollisionHashMapTest extends TestCase { - - public void testHash() { - try { - InputStream in = AnticollisionHashMapTest.class - .getResourceAsStream("/hashcollide.txt"); - BufferedReader br = new BufferedReader(new InputStreamReader(in)); - String line = br.readLine(); - br.close(); - String[] kvs = line.split("&"); - long start = System.currentTimeMillis(); - Map m = new AntiCollisionHashMap(); - for (String kv : kvs) { - String[] cols = kv.split("="); - m.put(cols[0], "test"); - } - System.out.println("map size: " + m.size()); - System.out.println("take time:" - + (System.currentTimeMillis() - start)); - - - m = new AntiCollisionHashMap(); - m.put("axmantest", "12345"); - m.put("axmantest1", "123451"); - m.put("axmantest2", "123452"); - m.put("axmantest3", "123453"); - System.out.println(m.get("axmantest")); - System.out.println(m.get("axmantest1")); - System.out.println(m.get("axmantest2")); - System.out.println(m.get("axmantest3")); - ByteArrayOutputStream buf = new ByteArrayOutputStream(); - ObjectOutputStream out = new ObjectOutputStream(buf); - out.writeObject(m); - out.flush(); - byte[] data = buf.toByteArray(); - out.close(); - - ByteArrayInputStream inbuf = new ByteArrayInputStream(data); - ObjectInputStream oin = new ObjectInputStream(inbuf); - - @SuppressWarnings("unchecked") - AntiCollisionHashMap m1 = (AntiCollisionHashMap)oin.readObject(); - oin.close(); - System.out.println(m1.get("axmantest")); - System.out.println(m1.get("axmantest1")); - System.out.println(m1.get("axmantest2")); - System.out.println(m1.get("axmantest3")); - -// start = System.currentTimeMillis(); -// Map m1 = new HashMap(); -// for (String kv : kvs) { -// String[] cols = kv.split("="); -// m1.put(cols[0], "test"); -// } -// System.out.println("map size: " + m.size()); -// System.out.println("take time:" -// + (System.currentTimeMillis() - start)); - } catch (Exception e) { - e.printStackTrace(); - } - - } -} diff --git a/src/test/java/com/alibaba/json/bvt/parser/FastMatchCheckTest.java b/src/test/java/com/alibaba/json/bvt/parser/FastMatchCheckTest.java index 0ae3883f8..8e591c52e 100755 --- a/src/test/java/com/alibaba/json/bvt/parser/FastMatchCheckTest.java +++ b/src/test/java/com/alibaba/json/bvt/parser/FastMatchCheckTest.java @@ -1,11 +1,11 @@ package com.alibaba.json.bvt.parser; -import org.junit.Assert; import junit.framework.TestCase; +import org.junit.Assert; + import com.alibaba.fastjson.parser.JSONToken; import com.alibaba.fastjson.parser.deserializer.ArrayDeserializer; -import com.alibaba.fastjson.parser.deserializer.ArrayListStringDeserializer; import com.alibaba.fastjson.parser.deserializer.AtomicIntegerArrayDeserializer; import com.alibaba.fastjson.parser.deserializer.AtomicLongArrayDeserializer; import com.alibaba.fastjson.parser.deserializer.CharacterDeserializer; @@ -22,7 +22,6 @@ import com.alibaba.fastjson.parser.deserializer.TimestampDeserializer; public class FastMatchCheckTest extends TestCase { public void test_match() throws Exception { Assert.assertEquals(JSONToken.LBRACKET, AtomicIntegerArrayDeserializer.instance.getFastMatchToken()); - Assert.assertEquals(JSONToken.LBRACKET, ArrayListStringDeserializer.instance.getFastMatchToken()); Assert.assertEquals(JSONToken.LBRACKET, AtomicLongArrayDeserializer.instance.getFastMatchToken()); Assert.assertEquals(JSONToken.LITERAL_STRING, InetAddressDeserializer.instance.getFastMatchToken()); Assert.assertEquals(JSONToken.LITERAL_STRING, LocaleDeserializer.instance.getFastMatchToken()); diff --git a/src/test/java/com/alibaba/json/bvt/parser/JSONScannerTest_symbol.java b/src/test/java/com/alibaba/json/bvt/parser/JSONScannerTest_symbol.java index 47fe12ce4..6a968b113 100755 --- a/src/test/java/com/alibaba/json/bvt/parser/JSONScannerTest_symbol.java +++ b/src/test/java/com/alibaba/json/bvt/parser/JSONScannerTest_symbol.java @@ -20,20 +20,7 @@ public class JSONScannerTest_symbol extends TestCase { JSONScanner lexer = new JSONScanner("\"name\""); String symbol = lexer.scanSymbol(symbolTable, '"'); Assert.assertTrue("name".equals(symbol)); - - String symbol2 = lexer.symbol(symbolTable); - Assert.assertTrue("name".equals(symbol2)); - } - - public void test_0_1() throws Exception { - SymbolTable symbolTable = new SymbolTable(); - - JSONScanner lexer = new JSONScanner("\"name\""); - lexer.scanString(); - String symbol = lexer.symbol(symbolTable); - Assert.assertTrue("name".equals(symbol)); - - Assert.assertTrue("name" != lexer.symbol(null)); + lexer.close(); } public void test_1() throws Exception { @@ -42,6 +29,7 @@ public class JSONScannerTest_symbol extends TestCase { JSONScanner lexer = new JSONScanner("\"nick name\""); String symbol = lexer.scanSymbol(symbolTable, '"'); Assert.assertTrue("nick name".equals(symbol)); + lexer.close(); } public void test_2() throws Exception { @@ -50,17 +38,7 @@ public class JSONScannerTest_symbol extends TestCase { JSONScanner lexer = new JSONScanner("\"nick \\\"name\""); String symbol = lexer.scanSymbol(symbolTable, '"'); Assert.assertTrue("nick \"name" == symbol); - } - - public void test_2_1() throws Exception { - SymbolTable symbolTable = new SymbolTable(); - - JSONScanner lexer = new JSONScanner("\"nick \\\"name\""); - lexer.scanString(); - String symbol = lexer.symbol(symbolTable); - Assert.assertTrue("nick \"name" == symbol); - - Assert.assertTrue("nick \"name" != lexer.symbol(null)); + lexer.close(); } public void test_3() throws Exception { @@ -69,6 +47,7 @@ public class JSONScannerTest_symbol extends TestCase { JSONScanner lexer = new JSONScanner("\"nick \\\\name\""); String symbol = lexer.scanSymbol(symbolTable, '"'); Assert.assertTrue("nick \\name" == symbol); + lexer.close(); } public void test_4() throws Exception { @@ -77,6 +56,7 @@ public class JSONScannerTest_symbol extends TestCase { JSONScanner lexer = new JSONScanner("\"nick \\/name\""); String symbol = lexer.scanSymbol(symbolTable, '"'); Assert.assertTrue("nick /name" == symbol); + lexer.close(); } public void test_5() throws Exception { @@ -85,6 +65,7 @@ public class JSONScannerTest_symbol extends TestCase { JSONScanner lexer = new JSONScanner("\"nick \\bname\""); String symbol = lexer.scanSymbol(symbolTable, '"'); Assert.assertTrue("nick \bname" == symbol); + lexer.close(); } public void test_6() throws Exception { @@ -93,6 +74,7 @@ public class JSONScannerTest_symbol extends TestCase { JSONScanner lexer = new JSONScanner("\"nick \\f name\""); String symbol = lexer.scanSymbol(symbolTable, '"'); Assert.assertTrue("nick \f name" == symbol); + lexer.close(); } public void test_7() throws Exception { @@ -101,6 +83,7 @@ public class JSONScannerTest_symbol extends TestCase { JSONScanner lexer = new JSONScanner("\"nick \\F name\""); String symbol = lexer.scanSymbol(symbolTable, '"'); Assert.assertTrue("nick \f name" == symbol); + lexer.close(); } public void test_8() throws Exception { @@ -109,6 +92,7 @@ public class JSONScannerTest_symbol extends TestCase { JSONScanner lexer = new JSONScanner("\"nick \\n name\""); String symbol = lexer.scanSymbol(symbolTable, '"'); Assert.assertTrue("nick \n name" == symbol); + lexer.close(); } public void test_9() throws Exception { @@ -117,6 +101,7 @@ public class JSONScannerTest_symbol extends TestCase { JSONScanner lexer = new JSONScanner("\"nick \\r name\""); String symbol = lexer.scanSymbol(symbolTable, '"'); Assert.assertTrue("nick \r name" == symbol); + lexer.close(); } public void test_10() throws Exception { @@ -125,6 +110,7 @@ public class JSONScannerTest_symbol extends TestCase { JSONScanner lexer = new JSONScanner("\"nick \\t name\""); String symbol = lexer.scanSymbol(symbolTable, '"'); Assert.assertTrue("nick \t name" == symbol); + lexer.close(); } public void test_11() throws Exception { @@ -133,6 +119,7 @@ public class JSONScannerTest_symbol extends TestCase { JSONScanner lexer = new JSONScanner("\"nick \\u4e2d name\""); String symbol = lexer.scanSymbol(symbolTable, '"'); Assert.assertTrue("nick 中 name" == symbol); + lexer.close(); } public void test_12() throws Exception { @@ -142,6 +129,7 @@ public class JSONScannerTest_symbol extends TestCase { "\"\\tabcdefghijklmnopqrstuvwxyz01234567890abcdefghijklmnopqrstuvwxyz01234567890abcdefghijklmnopqrstuvwxyz01234567890abcdefghijklmnopqrstuvwxyz01234567890\""); String symbol = lexer.scanSymbol(symbolTable, '"'); Assert.assertTrue("\tabcdefghijklmnopqrstuvwxyz01234567890abcdefghijklmnopqrstuvwxyz01234567890abcdefghijklmnopqrstuvwxyz01234567890abcdefghijklmnopqrstuvwxyz01234567890" == symbol); + lexer.close(); } public void test_error() throws Exception { @@ -151,6 +139,7 @@ public class JSONScannerTest_symbol extends TestCase { JSONScanner lexer = new JSONScanner("\"nick \\a name\""); lexer.scanSymbol(symbolTable, '"'); + lexer.close(); } catch (JSONException e) { error = e; } @@ -164,6 +153,7 @@ public class JSONScannerTest_symbol extends TestCase { JSONScanner lexer = new JSONScanner("\"name"); lexer.scanSymbol(symbolTable, '"'); + lexer.close(); } catch (JSONException e) { error = e; } diff --git a/src/test/java/com/alibaba/json/bvt/parser/deser/ArrayListTypeDeserializerTest.java b/src/test/java/com/alibaba/json/bvt/parser/deser/ArrayListTypeDeserializerTest.java index 2acd8c1c7..1ecfb39ef 100755 --- a/src/test/java/com/alibaba/json/bvt/parser/deser/ArrayListTypeDeserializerTest.java +++ b/src/test/java/com/alibaba/json/bvt/parser/deser/ArrayListTypeDeserializerTest.java @@ -6,6 +6,7 @@ import java.util.HashSet; import java.util.Set; import org.junit.Assert; + import junit.framework.TestCase; import com.alibaba.fastjson.JSON; @@ -65,6 +66,7 @@ public class ArrayListTypeDeserializerTest extends TestCase { return value; } + @SuppressWarnings("unused") public void setValue(ArrayList value) { this.value = value; } diff --git a/src/test/java/com/alibaba/json/bvt/parser/deser/DateFormatDeserializerTest.java b/src/test/java/com/alibaba/json/bvt/parser/deser/DateFormatDeserializerTest.java new file mode 100644 index 000000000..2660c1f6b --- /dev/null +++ b/src/test/java/com/alibaba/json/bvt/parser/deser/DateFormatDeserializerTest.java @@ -0,0 +1,59 @@ +package com.alibaba.json.bvt.parser.deser; + +import java.text.SimpleDateFormat; + +import junit.framework.TestCase; + +import org.junit.Assert; + +import com.alibaba.fastjson.JSON; + +public class DateFormatDeserializerTest extends TestCase { + + public void test_dateFormat_empty() throws Exception { + VO vo = JSON.parseObject("{\"format\":\"\"}", VO.class); + Assert.assertEquals(null, vo.getFormat()); + } + + public void test_dateFormat_null() throws Exception { + VO vo = JSON.parseObject("{\"format\":null}", VO.class); + Assert.assertEquals(null, vo.getFormat()); + } + + public void test_dateFormat_yyyy() throws Exception { + VO vo = JSON.parseObject("{\"format\":\"yyyy\"}", VO.class); + Assert.assertEquals(new SimpleDateFormat("yyyy"), vo.getFormat()); + } + + public void test_dateFormat_error() throws Exception { + Exception error = null; + try { + JSON.parseObject("{\"format\":123}", VO.class); + } catch (Exception e) { + error = e; + } + Assert.assertNotNull(error); + } + + public static class VO { + + private SimpleDateFormat format; + + public VO(){ + + } + + public VO(SimpleDateFormat format){ + this.format = format; + } + + public SimpleDateFormat getFormat() { + return format; + } + + public void setFormat(SimpleDateFormat format) { + this.format = format; + } + + } +} diff --git a/src/test/java/com/alibaba/json/bvt/parser/deser/DefaultObjectDeserializerTest2.java b/src/test/java/com/alibaba/json/bvt/parser/deser/DefaultObjectDeserializerTest2.java index 582b37b6e..a733a15e8 100755 --- a/src/test/java/com/alibaba/json/bvt/parser/deser/DefaultObjectDeserializerTest2.java +++ b/src/test/java/com/alibaba/json/bvt/parser/deser/DefaultObjectDeserializerTest2.java @@ -7,17 +7,18 @@ import java.util.TreeMap; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; -import org.junit.Assert; import junit.framework.TestCase; +import org.junit.Assert; + import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.TypeReference; import com.alibaba.fastjson.parser.DefaultExtJSONParser; import com.alibaba.fastjson.parser.ParserConfig; import com.alibaba.fastjson.parser.deserializer.DefaultObjectDeserializer; -import com.alibaba.fastjson.util.AntiCollisionHashMap; +@SuppressWarnings("deprecation") public class DefaultObjectDeserializerTest2 extends TestCase { public void test_0() throws Exception { @@ -52,7 +53,7 @@ public class DefaultObjectDeserializerTest2 extends TestCase { SortedMap map = JSON.parseObject(input, new TypeReference>() { }.getType()); - Assert.assertEquals(AntiCollisionHashMap.class, map.get("map").getClass()); + Assert.assertEquals(HashMap.class, map.get("map").getClass()); } public void test_3() throws Exception { diff --git a/src/test/java/com/alibaba/json/bvt/parser/stream/JSONReaderScannerTest_chars.java b/src/test/java/com/alibaba/json/bvt/parser/stream/JSONReaderScannerTest_chars.java new file mode 100644 index 000000000..ae271c78a --- /dev/null +++ b/src/test/java/com/alibaba/json/bvt/parser/stream/JSONReaderScannerTest_chars.java @@ -0,0 +1,46 @@ +package com.alibaba.json.bvt.parser.stream; + +import java.math.BigDecimal; + +import junit.framework.TestCase; + +import org.junit.Assert; + +import com.alibaba.fastjson.JSONObject; +import com.alibaba.fastjson.parser.DefaultJSONParser; +import com.alibaba.fastjson.parser.JSONReaderScanner; + +public class JSONReaderScannerTest_chars extends TestCase { + + public void test_double() throws Exception { + char[] chars = "{\"value\":3.5D}".toCharArray(); + DefaultJSONParser parser = new DefaultJSONParser(new JSONReaderScanner(chars, chars.length)); + JSONObject json = parser.parseObject(); + Assert.assertTrue(3.5D == ((Double) json.get("value")).doubleValue()); + parser.close(); + } + + public void test_float() throws Exception { + char[] chars = "{\"value\":3.5F}".toCharArray(); + DefaultJSONParser parser = new DefaultJSONParser(new JSONReaderScanner(chars, chars.length)); + JSONObject json = parser.parseObject(); + Assert.assertTrue(3.5F == ((Float) json.get("value")).doubleValue()); + parser.close(); + } + + public void test_decimal() throws Exception { + char[] chars = "{\"value\":3.5}".toCharArray(); + DefaultJSONParser parser = new DefaultJSONParser(new JSONReaderScanner(chars, chars.length)); + JSONObject json = parser.parseObject(); + Assert.assertEquals(new BigDecimal("3.5"), json.get("value")); + parser.close(); + } + + public void test_long() throws Exception { + char[] chars = "{\"value\":3L}".toCharArray(); + DefaultJSONParser parser = new DefaultJSONParser(new JSONReaderScanner(chars, chars.length)); + JSONObject json = parser.parseObject(); + Assert.assertTrue(3L == ((Long) json.get("value")).longValue()); + parser.close(); + } +} diff --git a/src/test/java/com/alibaba/json/bvt/parser/stream/JSONReaderScannerTest_enum.java b/src/test/java/com/alibaba/json/bvt/parser/stream/JSONReaderScannerTest_enum.java new file mode 100644 index 000000000..02217a719 --- /dev/null +++ b/src/test/java/com/alibaba/json/bvt/parser/stream/JSONReaderScannerTest_enum.java @@ -0,0 +1,57 @@ +package com.alibaba.json.bvt.parser.stream; + +import junit.framework.TestCase; + +import org.junit.Assert; + +import com.alibaba.fastjson.parser.DefaultJSONParser; +import com.alibaba.fastjson.parser.JSONReaderScanner; + +public class JSONReaderScannerTest_enum extends TestCase { + + public void test_a() throws Exception { + DefaultJSONParser parser = new DefaultJSONParser(new JSONReaderScanner("{\"type\":\"A\"}")); + VO vo = parser.parseObject(VO.class); + Assert.assertEquals(Type.A, vo.getType()); + parser.close(); + } + + public void test_b() throws Exception { + DefaultJSONParser parser = new DefaultJSONParser(new JSONReaderScanner("{\"type\":\"B\"}")); + VO vo = parser.parseObject(VO.class); + Assert.assertEquals(Type.B, vo.getType()); + parser.close(); + } + + public void test_c() throws Exception { + DefaultJSONParser parser = new DefaultJSONParser(new JSONReaderScanner("{\"type\":\"C\"}")); + VO vo = parser.parseObject(VO.class); + Assert.assertEquals(Type.C, vo.getType()); + parser.close(); + } + + public void test_x() throws Exception { + DefaultJSONParser parser = new DefaultJSONParser(new JSONReaderScanner("{\"type\":\"XXXXXXXXXXXXXXXXXXXXXXXX\"}")); + VO vo = parser.parseObject(VO.class); + Assert.assertEquals(Type.XXXXXXXXXXXXXXXXXXXXXXXX, vo.getType()); + parser.close(); + } + + public static class VO { + + private Type type; + + public Type getType() { + return type; + } + + public void setType(Type type) { + this.type = type; + } + + } + + public static enum Type { + A, B, C, D, XXXXXXXXXXXXXXXXXXXXXXXX + } +} diff --git a/src/test/java/com/alibaba/json/bvt/parser/stream/JSONReader_array.java b/src/test/java/com/alibaba/json/bvt/parser/stream/JSONReader_array.java new file mode 100644 index 000000000..8a2c4f7f5 --- /dev/null +++ b/src/test/java/com/alibaba/json/bvt/parser/stream/JSONReader_array.java @@ -0,0 +1,61 @@ +package com.alibaba.json.bvt.parser.stream; + +import java.io.StringReader; +import java.util.HashMap; +import java.util.Map; + +import junit.framework.TestCase; + +import org.junit.Assert; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONReader; + +public class JSONReader_array extends TestCase { + + public void test_array() throws Exception { + JSONReader reader = new JSONReader(new StringReader("[[],[],3,null,{\"name\":\"jobs\"},{\"id\":123},{\"id\":1},{\"id\":2}]")); + reader.startArray(); + + JSONArray first = (JSONArray) reader.readObject(); + JSONArray second = (JSONArray) reader.readObject(); + + Assert.assertNotNull(first); + Assert.assertNotNull(second); + + Assert.assertEquals(new Integer(3), reader.readInteger()); + Assert.assertNull(reader.readString()); + + { + Map map = new HashMap(); + reader.readObject(map); + Assert.assertEquals("jobs", map.get("name")); + } + + { + VO vo = new VO(); + reader.readObject(vo); + Assert.assertEquals(123, vo.getId()); + } + + while (reader.hasNext()) { + VO vo = reader.readObject(VO.class); + Assert.assertNotNull(vo); + } + reader.endArray(); + reader.close(); + } + + public static class VO { + + private int id; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + } +} diff --git a/src/test/java/com/alibaba/json/bvt/parser/stream/JSONReader_map.java b/src/test/java/com/alibaba/json/bvt/parser/stream/JSONReader_map.java new file mode 100644 index 000000000..797d2970d --- /dev/null +++ b/src/test/java/com/alibaba/json/bvt/parser/stream/JSONReader_map.java @@ -0,0 +1,40 @@ +package com.alibaba.json.bvt.parser.stream; + +import java.io.StringReader; +import java.util.HashMap; +import java.util.Map; + +import junit.framework.TestCase; + +import org.junit.Assert; + +import com.alibaba.fastjson.JSONReader; + +public class JSONReader_map extends TestCase { + + public void test_array() throws Exception { + JSONReader reader = new JSONReader(new StringReader("[{\"id\":123}]")); + + reader.startArray(); + + Map map = new HashMap(); + reader.readObject(map); + + Assert.assertEquals(123, map.get("id")); + + reader.endArray(); + + reader.close(); + } + + public void test_map() throws Exception { + JSONReader reader = new JSONReader(new StringReader("{\"id\":123}")); + + Map map = new HashMap(); + reader.readObject(map); + + Assert.assertEquals(123, map.get("id")); + + reader.close(); + } +} diff --git a/src/test/java/com/alibaba/json/bvt/parser/stream/JSONReader_obj.java b/src/test/java/com/alibaba/json/bvt/parser/stream/JSONReader_obj.java new file mode 100644 index 000000000..c9f8ba547 --- /dev/null +++ b/src/test/java/com/alibaba/json/bvt/parser/stream/JSONReader_obj.java @@ -0,0 +1,52 @@ +package com.alibaba.json.bvt.parser.stream; + +import java.io.StringReader; + +import junit.framework.TestCase; + +import org.junit.Assert; + +import com.alibaba.fastjson.JSONReader; + +public class JSONReader_obj extends TestCase { + + public void test_array() throws Exception { + JSONReader reader = new JSONReader(new StringReader("[{\"id\":123}]")); + + reader.startArray(); + + VO vo = new VO(); + reader.readObject(vo); + + Assert.assertEquals(123, vo.getId()); + + reader.endArray(); + + reader.close(); + } + + public void test_obj() throws Exception { + JSONReader reader = new JSONReader(new StringReader("{\"id\":123}")); + + VO vo = new VO(); + reader.readObject(vo); + + Assert.assertEquals(123, vo.getId()); + + reader.close(); + } + + public static class VO { + + private int id; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + } +} diff --git a/src/test/java/com/alibaba/json/bvt/parser/stream/JSONReader_obj_2.java b/src/test/java/com/alibaba/json/bvt/parser/stream/JSONReader_obj_2.java new file mode 100644 index 000000000..d6585f874 --- /dev/null +++ b/src/test/java/com/alibaba/json/bvt/parser/stream/JSONReader_obj_2.java @@ -0,0 +1,50 @@ +package com.alibaba.json.bvt.parser.stream; + +import java.io.StringReader; + +import junit.framework.TestCase; + +import org.junit.Assert; + +import com.alibaba.fastjson.JSONReader; + +public class JSONReader_obj_2 extends TestCase { + + public void test_array() throws Exception { + JSONReader reader = new JSONReader(new StringReader("[{\"id\":123}]")); + + reader.startArray(); + + VO vo = reader.readObject(VO.class); + + Assert.assertEquals(123, vo.getId()); + + reader.endArray(); + + reader.close(); + } + + public void test_obj() throws Exception { + JSONReader reader = new JSONReader(new StringReader("{\"id\":123}")); + + VO vo = reader.readObject(VO.class); + + Assert.assertEquals(123, vo.getId()); + + reader.close(); + } + + public static class VO { + + private int id; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + } +} diff --git a/src/test/java/com/alibaba/json/bvt/parser/stream/JSONReader_obj_3.java b/src/test/java/com/alibaba/json/bvt/parser/stream/JSONReader_obj_3.java new file mode 100644 index 000000000..e50a7e727 --- /dev/null +++ b/src/test/java/com/alibaba/json/bvt/parser/stream/JSONReader_obj_3.java @@ -0,0 +1,61 @@ +package com.alibaba.json.bvt.parser.stream; + +import java.io.StringReader; + +import junit.framework.TestCase; + +import org.junit.Assert; + +import com.alibaba.fastjson.JSONReader; + +public class JSONReader_obj_3 extends TestCase { + + public void test_obj() throws Exception { + JSONReader reader = new JSONReader(new StringReader("{\"id\":123}")); + + reader.startObject(); + Assert.assertEquals("id", reader.readString()); + Assert.assertEquals(Integer.valueOf(123), reader.readInteger()); + reader.endObject(); + + reader.close(); + } + + public void test_obj_2() throws Exception { + JSONReader reader = new JSONReader(new StringReader("{\"val\":{\"id\":123}}")); + + reader.startObject(); + + Assert.assertEquals("val", reader.readString()); + + reader.startObject(); + Assert.assertEquals("id", reader.readString()); + Assert.assertEquals(Integer.valueOf(123), reader.readInteger()); + reader.endObject(); + + reader.endObject(); + + reader.close(); + } + + public void test_obj_3() throws Exception { + JSONReader reader = new JSONReader(new StringReader("{\"val\":{\"val\":{\"id\":123}}}")); + + reader.startObject(); + Assert.assertEquals("val", reader.readString()); + + reader.startObject(); + Assert.assertEquals("val", reader.readString()); + + reader.startObject(); + Assert.assertEquals("id", reader.readString()); + Assert.assertEquals(Long.valueOf(123), reader.readLong()); + reader.endObject(); + + reader.endObject(); + reader.endObject(); + + reader.close(); + } + +} diff --git a/src/test/java/com/alibaba/json/bvt/parser/stream/JSONReader_string.java b/src/test/java/com/alibaba/json/bvt/parser/stream/JSONReader_string.java new file mode 100644 index 000000000..32bedd931 --- /dev/null +++ b/src/test/java/com/alibaba/json/bvt/parser/stream/JSONReader_string.java @@ -0,0 +1,63 @@ +package com.alibaba.json.bvt.parser.stream; + +import java.io.StringReader; + +import junit.framework.TestCase; + +import org.junit.Assert; + +import com.alibaba.fastjson.JSONReader; + +public class JSONReader_string extends TestCase { + + public void test_array() throws Exception { + JSONReader reader = new JSONReader(new StringReader("[\"abc\"]")); + + reader.startArray(); + + Assert.assertEquals("abc", reader.readString()); + + reader.endArray(); + + reader.close(); + } + + public void test_array_2() throws Exception { + JSONReader reader = new JSONReader(new StringReader("[[\"abc\"]]")); + + reader.startArray(); + reader.startArray(); + + Assert.assertEquals("abc", reader.readString()); + + reader.endArray(); + reader.endArray(); + + reader.close(); + } + + public void test_array_3() throws Exception { + JSONReader reader = new JSONReader(new StringReader("[[[\"abc\"]]]")); + + reader.startArray(); + reader.startArray(); + reader.startArray(); + + Assert.assertEquals("abc", reader.readString()); + + reader.endArray(); + reader.endArray(); + reader.endArray(); + + reader.close(); + } + + public void test_obj() throws Exception { + JSONReader reader = new JSONReader(new StringReader("\"abc\"")); + + Assert.assertEquals("abc", reader.readString()); + + reader.close(); + } + +} diff --git a/src/test/java/com/alibaba/json/bvt/parser/stream/JSONReader_typeRef.java b/src/test/java/com/alibaba/json/bvt/parser/stream/JSONReader_typeRef.java new file mode 100644 index 000000000..b9fc55ae9 --- /dev/null +++ b/src/test/java/com/alibaba/json/bvt/parser/stream/JSONReader_typeRef.java @@ -0,0 +1,49 @@ +package com.alibaba.json.bvt.parser.stream; + +import java.io.StringReader; +import java.util.List; + +import junit.framework.TestCase; + +import org.junit.Assert; + +import com.alibaba.fastjson.JSONReader; +import com.alibaba.fastjson.TypeReference; + +public class JSONReader_typeRef extends TestCase { + public void test_array() throws Exception { + JSONReader reader = new JSONReader(new StringReader("[{\"id\":123}]")); + + List list = reader.readObject(new TypeReference>() {}.getType()); + + Assert.assertEquals(123, list.get(0).getId()); + + reader.close(); + } + + public void test_array_1() throws Exception { + JSONReader reader = new JSONReader(new StringReader("[[{\"id\":123}]]")); + + reader.startArray(); + List list = reader.readObject(new TypeReference>() {}.getType()); + + Assert.assertEquals(123, list.get(0).getId()); + + reader.endArray(); + + reader.close(); + } + + public static class VO { + + private int id; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + } +} diff --git a/src/test/java/com/alibaba/json/bvt/serializer/ColorSerializerTest.java b/src/test/java/com/alibaba/json/bvt/serializer/ColorSerializerTest.java index 3b38a2fb5..7a52ab31e 100755 --- a/src/test/java/com/alibaba/json/bvt/serializer/ColorSerializerTest.java +++ b/src/test/java/com/alibaba/json/bvt/serializer/ColorSerializerTest.java @@ -1,37 +1,50 @@ package com.alibaba.json.bvt.serializer; import java.awt.Color; -import java.awt.Rectangle; + +import junit.framework.TestCase; import org.junit.Assert; -import junit.framework.TestCase; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.serializer.ColorSerializer; import com.alibaba.fastjson.serializer.JSONSerializer; import com.alibaba.fastjson.serializer.SerializerFeature; - public class ColorSerializerTest extends TestCase { - + public void test_null() throws Exception { JSONSerializer serializer = new JSONSerializer(); Assert.assertEquals(ColorSerializer.class, serializer.getObjectWriter(Color.class).getClass()); - + VO vo = new VO(); - + Assert.assertEquals("{\"value\":null}", JSON.toJSONString(vo, SerializerFeature.WriteMapNullValue)); } + public void test_rgb() throws Exception { + JSONSerializer serializer = new JSONSerializer(); + Assert.assertEquals(ColorSerializer.class, serializer.getObjectWriter(Color.class).getClass()); + + VO vo = new VO(); + vo.setValue(new Color(1,1,1,0)); + + Assert.assertEquals("{\"value\":{\"r\":1,\"g\":1,\"b\":1}}", JSON.toJSONString(vo, SerializerFeature.WriteMapNullValue)); + } + + public void test_rgb_getAutowiredFor() throws Exception { + + } + private static class VO { - private Rectangle value; + private Color value; - public Rectangle getValue() { + public Color getValue() { return value; } - public void setValue(Rectangle value) { + public void setValue(Color value) { this.value = value; } diff --git a/src/test/java/com/alibaba/json/bvt/serializer/DateFormatSerializerTest.java b/src/test/java/com/alibaba/json/bvt/serializer/DateFormatSerializerTest.java new file mode 100644 index 000000000..f444876ea --- /dev/null +++ b/src/test/java/com/alibaba/json/bvt/serializer/DateFormatSerializerTest.java @@ -0,0 +1,82 @@ +package com.alibaba.json.bvt.serializer; + +import java.text.SimpleDateFormat; +import java.util.Date; + +import junit.framework.TestCase; + +import org.junit.Assert; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.serializer.DateFormatSerializer; +import com.alibaba.fastjson.serializer.JSONSerializer; +import com.alibaba.fastjson.serializer.SerializeConfig; +import com.alibaba.fastjson.serializer.SerializeWriter; +import com.alibaba.fastjson.serializer.SerializerFeature; + +public class DateFormatSerializerTest extends TestCase { + + public void test_date() throws Exception { + Assert.assertEquals("{\"format\":null}", JSON.toJSONString(new VO(), SerializerFeature.WriteMapNullValue)); + } + + public void test_date_2() throws Exception { + SerializeWriter out = new SerializeWriter(); + SerializeConfig config = new SerializeConfig(); + config.put(Date.class, DateFormatSerializer.instance); + JSONSerializer serializer = new JSONSerializer(out, config); + + serializer.config(SerializerFeature.WriteMapNullValue, true); + serializer.write(new VO()); + + Assert.assertEquals("{\"format\":null}", out.toString()); + } + + public void test_date_3() throws Exception { + SerializeWriter out = new SerializeWriter(); + SerializeConfig config = new SerializeConfig(); + config.put(Date.class, DateFormatSerializer.instance); + JSONSerializer serializer = new JSONSerializer(out, config); + + serializer.config(SerializerFeature.WriteClassName, true); + serializer.write(new VO()); + + Assert.assertEquals("{\"@type\":\"com.alibaba.json.bvt.serializer.DateFormatSerializerTest$VO\"}", + out.toString()); + } + + public void test_date_4() throws Exception { + SerializeWriter out = new SerializeWriter(); + SerializeConfig config = new SerializeConfig(); + config.put(Date.class, DateFormatSerializer.instance); + JSONSerializer serializer = new JSONSerializer(out, config); + + serializer.write(new VO(new SimpleDateFormat("yyyy"))); + + Assert.assertEquals("{\"format\":\"yyyy\"}", out.toString()); + + JSON.parseObject(out.toString(), VO.class); + } + + public static class VO { + + private SimpleDateFormat format; + + public VO(){ + + } + + public VO(SimpleDateFormat format){ + this.format = format; + } + + public SimpleDateFormat getFormat() { + return format; + } + + public void setFormat(SimpleDateFormat format) { + this.format = format; + } + + } +} diff --git a/src/test/java/com/alibaba/json/bvt/serializer/EnumerationSeriliazerTest.java b/src/test/java/com/alibaba/json/bvt/serializer/EnumerationSeriliazerTest.java new file mode 100644 index 000000000..e417909d3 --- /dev/null +++ b/src/test/java/com/alibaba/json/bvt/serializer/EnumerationSeriliazerTest.java @@ -0,0 +1,58 @@ +package com.alibaba.json.bvt.serializer; + +import java.util.Enumeration; +import java.util.Vector; + +import junit.framework.TestCase; + +import org.junit.Assert; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.serializer.SerializerFeature; + +public class EnumerationSeriliazerTest extends TestCase { + + public void test_nullAsEmtpyList() throws Exception { + VO e = new VO(); + Assert.assertEquals("{\"elements\":[]}", JSON.toJSONString(e, SerializerFeature.WriteMapNullValue, + SerializerFeature.WriteNullListAsEmpty)); + } + + public void test_null() throws Exception { + VO e = new VO(); + Assert.assertEquals("{\"elements\":null}", JSON.toJSONString(e, SerializerFeature.WriteMapNullValue)); + } + + public void test_1() throws Exception { + VO e = new VO(new Entity(),new Entity()); + Assert.assertEquals("{\"elements\":[{},{}]}", JSON.toJSONString(e, SerializerFeature.WriteMapNullValue)); + } + + private static class VO { + + private Enumeration elements; + + public VO(Entity... array){ + if (array.length > 0) { + Vector vector = new Vector(); + for (Entity item : array) { + vector.add(item); + } + this.elements = vector.elements(); + } + } + + public Enumeration getElements() { + return elements; + } + + public void setElements(Enumeration elements) { + this.elements = elements; + } + + } + + public static class Entity { + + } +} diff --git a/src/test/java/com/alibaba/json/bvt/serializer/PascalNameFilterTest_1.java b/src/test/java/com/alibaba/json/bvt/serializer/PascalNameFilterTest_1.java new file mode 100644 index 000000000..1d442ae05 --- /dev/null +++ b/src/test/java/com/alibaba/json/bvt/serializer/PascalNameFilterTest_1.java @@ -0,0 +1,30 @@ +package com.alibaba.json.bvt.serializer; + +import java.util.LinkedHashMap; +import java.util.Map; + +import junit.framework.TestCase; + +import org.junit.Assert; + +import com.alibaba.fastjson.serializer.JSONSerializer; +import com.alibaba.fastjson.serializer.PascalNameFilter; + +public class PascalNameFilterTest_1 extends TestCase { + + public void test_0() throws Exception { + JSONSerializer serializer = new JSONSerializer(); + serializer.getNameFilters().add(new PascalNameFilter()); + + Map vo = new LinkedHashMap(); + vo.put("", 123); + vo.put(null, "wenshao"); + + serializer.write(vo); + + Assert.assertEquals("{\"\":123,null:\"wenshao\"}", serializer.toString()); + + serializer.close(); + } + +} diff --git a/src/test/java/com/alibaba/json/bvt/support/spring/FastJsonHttpMessageConverterTest.java b/src/test/java/com/alibaba/json/bvt/support/spring/FastJsonHttpMessageConverterTest.java index 76ba59870..c7dc52df6 100644 --- a/src/test/java/com/alibaba/json/bvt/support/spring/FastJsonHttpMessageConverterTest.java +++ b/src/test/java/com/alibaba/json/bvt/support/spring/FastJsonHttpMessageConverterTest.java @@ -1,19 +1,74 @@ package com.alibaba.json.bvt.support.spring; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; import java.nio.charset.Charset; import junit.framework.TestCase; import org.junit.Assert; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpInputMessage; +import org.springframework.http.HttpOutputMessage; +import org.springframework.http.MediaType; import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter; public class FastJsonHttpMessageConverterTest extends TestCase { - public void test_() throws Exception { - FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter(); - converter.setCharset(Charset.forName("UTF-8")); - Assert.assertEquals(Charset.forName("UTF-8"), converter.getCharset()); - - Assert.assertEquals(0, converter.getFeatures().length); - } + + public void test_read() throws Exception { + FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter(); + converter.setCharset(Charset.forName("UTF-8")); + Assert.assertEquals(Charset.forName("UTF-8"), converter.getCharset()); + + Assert.assertEquals(0, converter.getFeatures().length); + + HttpInputMessage input = new HttpInputMessage() { + + public HttpHeaders getHeaders() { + // TODO Auto-generated method stub + return null; + } + + public InputStream getBody() throws IOException { + return new ByteArrayInputStream("{\"id\":123}".getBytes(Charset.forName("UTF-8"))); + } + + }; + VO vo = (VO) converter.read(VO.class, input); + Assert.assertEquals(123, vo.getId()); + + final ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); + HttpOutputMessage out = new HttpOutputMessage() { + + public HttpHeaders getHeaders() { + return new HttpHeaders(); + } + + public OutputStream getBody() throws IOException { + return byteOut; + } + }; + converter.write(vo, MediaType.TEXT_PLAIN, out); + + byte[] bytes = byteOut.toByteArray(); + Assert.assertEquals("{\"id\":123}", new String(bytes, "UTF-8")); + } + + public static class VO { + + private int id; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + } } diff --git a/src/test/java/com/alibaba/json/bvt/support/spring/FastJsonJsonViewTest.java b/src/test/java/com/alibaba/json/bvt/support/spring/FastJsonJsonViewTest.java new file mode 100644 index 000000000..392697f48 --- /dev/null +++ b/src/test/java/com/alibaba/json/bvt/support/spring/FastJsonJsonViewTest.java @@ -0,0 +1,43 @@ +package com.alibaba.json.bvt.support.spring; + +import java.nio.charset.Charset; +import java.util.HashMap; +import java.util.Map; + +import junit.framework.TestCase; + +import org.junit.Assert; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; + +import com.alibaba.fastjson.serializer.SerializerFeature; +import com.alibaba.fastjson.support.spring.FastJsonJsonView; + +public class FastJsonJsonViewTest extends TestCase { + + @SuppressWarnings("deprecation") + public void test_0() throws Exception { + FastJsonJsonView view = new FastJsonJsonView(); + + Assert.assertEquals(Charset.forName("UTF-8"), view.getCharset()); + view.setCharset(Charset.forName("GBK")); + Assert.assertEquals(Charset.forName("GBK"), view.getCharset()); + + Assert.assertNotNull(view.getFeatures()); + Assert.assertEquals(0, view.getFeatures().length); + + view.setSerializerFeature(SerializerFeature.BrowserCompatible); + Assert.assertEquals(1, view.getFeatures().length); + Assert.assertEquals(SerializerFeature.BrowserCompatible, view.getFeatures()[0]); + + view.setFeatures(SerializerFeature.DisableCheckSpecialChar, SerializerFeature.SortField); + Assert.assertEquals(2, view.getFeatures().length); + Assert.assertEquals(SerializerFeature.DisableCheckSpecialChar, view.getFeatures()[0]); + Assert.assertEquals(SerializerFeature.SortField, view.getFeatures()[1]); + + Map model = new HashMap(); + MockHttpServletRequest request = new MockHttpServletRequest(); + MockHttpServletResponse response = new MockHttpServletResponse(); + view.render(model, request, response); + } +}