Skip to content

Commit

Permalink
bug fixed.
Browse files Browse the repository at this point in the history
  • Loading branch information
wenshao committed May 10, 2018
1 parent d6b7c15 commit 9346be1
Show file tree
Hide file tree
Showing 11 changed files with 383 additions and 13 deletions.
8 changes: 7 additions & 1 deletion src/main/java/com/alibaba/fastjson/asm/TypeCollector.java
@@ -1,10 +1,16 @@
package com.alibaba.fastjson.asm;

import com.alibaba.fastjson.annotation.JSONType;
import com.alibaba.fastjson.util.ASMUtils;
import com.alibaba.fastjson.util.TypeUtils;

import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Map;

public class TypeCollector {
private static String JSONType = ASMUtils.desc(com.alibaba.fastjson.annotation.JSONType.class);

private static final Map<String, String> primitives = new HashMap<String, String>() {
{
put("int","I");
Expand Down Expand Up @@ -65,7 +71,7 @@ protected MethodCollector visitMethod(int access, String name, String desc) {
}

public void visitAnnotation(String desc) {
if ("Lcom/alibaba/fastjson/annotation/JSONType;".equals(desc)) {
if (JSONType.equals(desc)) {
jsonType = true;
}
}
Expand Down
7 changes: 7 additions & 0 deletions src/main/java/com/alibaba/fastjson/parser/ParserConfig.java
Expand Up @@ -376,6 +376,13 @@ public void setAsmEnable(boolean asmEnable) {
this.asmEnable = asmEnable;
}

/**
* @deprecated
*/
public IdentityHashMap<Type, ObjectDeserializer> getDerializers() {
return deserializers;
}

public IdentityHashMap<Type, ObjectDeserializer> getDeserializers() {
return deserializers;
}
Expand Down
Expand Up @@ -484,17 +484,27 @@ protected <T> T deserialze(DefaultJSONParser parser, //
if (customDeserilizer && lexer.matchField(name_chars)) {
matchField = true;
} else if (fieldClass == int.class || fieldClass == Integer.class) {
fieldValue = lexer.scanFieldInt(name_chars);

int intVal = lexer.scanFieldInt(name_chars);
if (intVal == 0 && lexer.matchStat == JSONLexer.VALUE_NULL) {
fieldValue = null;
} else {
fieldValue = intVal;
}

if (lexer.matchStat > 0) {
matchField = true;
valueParsed = true;
} else if (lexer.matchStat == JSONLexer.NOT_MATCH_NAME) {
continue;
}
} else if (fieldClass == long.class || fieldClass == Long.class) {
fieldValue = lexer.scanFieldLong(name_chars);

long longVal = lexer.scanFieldLong(name_chars);
if (longVal == 0 && lexer.matchStat == JSONLexer.VALUE_NULL) {
fieldValue = null;
} else {
fieldValue = longVal;
}

if (lexer.matchStat > 0) {
matchField = true;
valueParsed = true;
Expand Down Expand Up @@ -538,7 +548,13 @@ protected <T> T deserialze(DefaultJSONParser parser, //
continue;
}
} else if (fieldClass == boolean.class || fieldClass == Boolean.class) {
fieldValue = lexer.scanFieldBoolean(name_chars);
boolean booleanVal = lexer.scanFieldBoolean(name_chars);

if (lexer.matchStat == JSONLexer.VALUE_NULL) {
fieldValue = null;
} else {
fieldValue = booleanVal;
}

if (lexer.matchStat > 0) {
matchField = true;
Expand All @@ -547,17 +563,27 @@ protected <T> T deserialze(DefaultJSONParser parser, //
continue;
}
} else if (fieldClass == float.class || fieldClass == Float.class) {
fieldValue = lexer.scanFieldFloat(name_chars);

float floatVal = lexer.scanFieldFloat(name_chars);
if (floatVal == 0 && lexer.matchStat == JSONLexer.VALUE_NULL) {
fieldValue = null;
} else {
fieldValue = floatVal;
}

if (lexer.matchStat > 0) {
matchField = true;
valueParsed = true;
} else if (lexer.matchStat == JSONLexer.NOT_MATCH_NAME) {
continue;
}
} else if (fieldClass == double.class || fieldClass == Double.class) {
fieldValue = lexer.scanFieldDouble(name_chars);

double doubleVal = lexer.scanFieldDouble(name_chars);
if (doubleVal == 0 && lexer.matchStat == JSONLexer.VALUE_NULL) {
fieldValue = null;
} else {
fieldValue = doubleVal;
}

if (lexer.matchStat > 0) {
matchField = true;
valueParsed = true;
Expand Down Expand Up @@ -873,8 +899,25 @@ protected <T> T deserialze(DefaultJSONParser parser, //
}

if (beanInfo.creatorConstructor != null) {
boolean hasNull = false;
if (beanInfo.kotlin) {
for (int i = 0; i < params.length; i++) {
if (params[i] == null && beanInfo.fields != null && i < beanInfo.fields.length) {
FieldInfo fieldInfo = beanInfo.fields[i];
if (fieldInfo.fieldClass == String.class) {
hasNull = true;
}
break;
}
}
}

try {
object = beanInfo.creatorConstructor.newInstance(params);
if (hasNull && beanInfo.kotlinDefaultConstructor != null) {
object = beanInfo.kotlinDefaultConstructor.newInstance(new Object[0]);
} else {
object = beanInfo.creatorConstructor.newInstance(params);
}
} catch (Exception e) {
throw new JSONException("create instance error, " + paramNames + ", "
+ beanInfo.creatorConstructor.toGenericString(), e);
Expand Down
Expand Up @@ -702,6 +702,14 @@ public void writeEnum(Enum<?> value) {
}
}

/**
* @deprecated
*/
public void writeLongAndChar(long i, char c) throws IOException {
writeLong(i);
write(c);
}

public void writeLong(long i) {
boolean needQuotationMark = isEnabled(SerializerFeature.BrowserCompatible) //
&& (!isEnabled(SerializerFeature.WriteClassName)) //
Expand Down
63 changes: 62 additions & 1 deletion src/main/java/com/alibaba/fastjson/util/IOUtils.java
Expand Up @@ -491,7 +491,10 @@ public static byte[] decodeBase64(String chars, int offset, int charsLen) {
int d = 0;
for (int cc = 0, eLen = (len / 3) * 3; d < eLen;) {
// Assemble three bytes into an int from four "valid" characters.
int i = IA[chars.charAt(sIx++)] << 18 | IA[chars.charAt(sIx++)] << 12 | IA[chars.charAt(sIx++)] << 6 | IA[chars.charAt(sIx++)];
int i = IA[chars.charAt(sIx++)] << 18
| IA[chars.charAt(sIx++)] << 12
| IA[chars.charAt(sIx++)] << 6
| IA[chars.charAt(sIx++)];

// Add the bytes
bytes[d++] = (byte) (i >> 16);
Expand All @@ -518,6 +521,64 @@ public static byte[] decodeBase64(String chars, int offset, int charsLen) {
return bytes;
}

private int decode0(String src, int sp, int sl, byte[] bytes) {

int[] base64 = IA;
int dp = 0;
int bits = 0;
int shiftto = 18; // pos of first byte of 4-byte atom
while (sp < sl) {
int b = src.charAt(sp++) & 0xff;
if ((b = base64[b]) < 0) {
if (b == -2) { // padding byte '='
// = shiftto==18 unnecessary padding
// x= shiftto==12 a dangling single x
// x to be handled together with non-padding case
// xx= shiftto==6&&sp==sl missing last =
// xx=y shiftto==6 last is not =
if (shiftto == 6 && (sp == sl || src.charAt(sp++) != '=') ||
shiftto == 18) {
throw new IllegalArgumentException(
"Input byte array has wrong 4-byte ending unit");
}
break;
}
throw new IllegalArgumentException(
"Illegal base64 character " +
Integer.toString(src.charAt(sp - 1), 16));
}
bits |= (b << shiftto);
shiftto -= 6;
if (shiftto < 0) {
bytes[dp++] = (byte)(bits >> 16);
bytes[dp++] = (byte)(bits >> 8);
bytes[dp++] = (byte)(bits);
shiftto = 18;
bits = 0;
}
}
// reached end of byte array or hit padding '=' characters.
if (shiftto == 6) {
bytes[dp++] = (byte)(bits >> 16);
} else if (shiftto == 0) {
bytes[dp++] = (byte)(bits >> 16);
bytes[dp++] = (byte)(bits >> 8);
} else if (shiftto == 12) {
// dangling single "x", incorrectly encoded.
throw new IllegalArgumentException(
"Last unit does not have enough valid bits");
}
// anything left is invalid, if is not MIME.
// if MIME, ignore all non-base64 character
while (sp < sl) {
if (base64[src.charAt(sp++) & 0xff] < 0)
continue;
throw new IllegalArgumentException(
"Input byte array has incorrect ending byte at " + sp);
}
return dp;
}

/**
* Decodes a BASE64 encoded string that is known to be resonably well formatted. The method is about twice as fast
* as decode(String). The preconditions are:<br>
Expand Down
10 changes: 9 additions & 1 deletion src/main/java/com/alibaba/fastjson/util/JavaBeanInfo.java
Expand Up @@ -46,6 +46,9 @@ public class JavaBeanInfo {
public Type[] creatorConstructorParameterTypes;
public String[] creatorConstructorParameters;

public boolean kotlin;
public Constructor<?> kotlinDefaultConstructor;

public JavaBeanInfo(Class<?> clazz, //
Class<?> builderClass, //
Constructor<?> defaultConstructor, //
Expand Down Expand Up @@ -123,9 +126,14 @@ public JavaBeanInfo(Class<?> clazz, //
this.creatorConstructorParameterTypes = creatorConstructor.getParameterTypes();


boolean kotlin = TypeUtils.isKotlin(clazz);
kotlin = TypeUtils.isKotlin(clazz);
if (kotlin) {
this.creatorConstructorParameters = TypeUtils.getKoltinConstructorParameters(clazz);
try {
this.kotlinDefaultConstructor = clazz.getConstructor();
} catch (Throwable ex) {
// skip
}

Annotation[][] paramAnnotationArrays = creatorConstructor.getParameterAnnotations();
for (int i = 0; i < creatorConstructorParameters.length && i < paramAnnotationArrays.length; ++i) {
Expand Down
25 changes: 25 additions & 0 deletions src/test/java/com/alibaba/json/bvt/issue_1800/Issue1821.java
@@ -0,0 +1,25 @@
package com.alibaba.json.bvt.issue_1800;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.annotation.JSONField;
import com.alibaba.fastjson.annotation.JSONType;
import junit.framework.TestCase;

public class Issue1821 extends TestCase {
public void test_for_issue() throws Exception {
String str = "{\"type\":800,\"data\":\"HuYgMIxwfqdtvOJNv6kK025g5fh3yFHI2kaByO7udKk6FOBC3PGRWkGfwV0\\/vWQW6roN5ftKDHFZ3PWl0715OYue0rZj\\/VwrNsMvIL4MqTUNBBUGFU9SgZu87ss7RqmyijH6\\/sM968cK1Dv5U7Rrw79idl\\/hW8SILLn1YXvUa60=\"}";
Model m = JSON.parseObject(str, Model.class);


}

@JSONType
public static class Model {
@JSONField(name="type")
public int type;

@JSONField(name="data")
public byte[] data;
}

}
@@ -0,0 +1,75 @@
package com.alibaba.json.bvt.issue_1800;

import com.alibaba.fastjson.JSON;
import junit.framework.TestCase;

public class Issue_for_dianxing extends TestCase {
public void test_0() throws Exception {
String s = "{\"alarmLevel\":null,\"error\":null,\"errorCount\":0,\"maxAlarmCount\":10,\"warn\":null,"
+ "\"warnCount\":0}";
TopAlarm b = JSON.parseObject(s, TopAlarm.class);
System.out.println(JSON.toJSONString(b));
}

public static class TopAlarm {

private Double error; //为null表示不报警
private int errorCount;
private Double warn; //为null表示不报警
private int warnCount;
private Integer alarmLevel;
private int maxAlarmCount = 10;

public TopAlarm() {
}

public Double getError() {
return error;
}

public void setError(Double error) {
this.error = error;
}

public Double getWarn() {
return warn;
}

public void setWarn(Double warn) {
this.warn = warn;
}

public int getErrorCount() {
return errorCount;
}

public void setErrorCount(int errorCount) {
this.errorCount = errorCount;
}

public int getWarnCount() {
return warnCount;
}

public void setWarnCount(int warnCount) {
this.warnCount = warnCount;
}

public Integer getAlarmLevel() {
return alarmLevel;
}

public void setAlarmLevel(Integer alarmLevel) {
this.alarmLevel = alarmLevel;
}

public int getMaxAlarmCount() {
return maxAlarmCount;
}

public void setMaxAlarmCount(int maxAlarmCount) {
this.maxAlarmCount = maxAlarmCount;
}

}
}

0 comments on commit 9346be1

Please sign in to comment.