package com.alibaba.fastjson.parser.deserializer;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;

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;
import com.alibaba.fastjson.parser.ParseContext;
import com.alibaba.fastjson.parser.ParserConfig;
import com.alibaba.fastjson.util.FieldInfo;

public class ArrayListTypeFieldDeserializer extends FieldDeserializer {

    private final Type itemType;
    private int itemFastMatchToken;
    private ObjectDeserializer deserializer;

    public ArrayListTypeFieldDeserializer(ParserConfig mapping, Class<?> clazz, FieldInfo fieldInfo) {
        super(clazz, fieldInfo);

        Type fieldType = fieldInfo.fieldType;
        if (fieldType instanceof ParameterizedType) {
            this.itemType = ((ParameterizedType) fieldInfo.fieldType).getActualTypeArguments()[0];
        } else {
            this.itemType = Object.class;
        }
    }

    public int getFastMatchToken() {
        return JSONToken.LBRACKET;
    }

    @SuppressWarnings("rawtypes")
    @Override
    public void parseField(DefaultJSONParser parser, Object object, Type objectType, Map<String, Object> fieldValues) {
        if (parser.lexer.token() == JSONToken.NULL) {
            setValue(object, null);
            return;
        }

        ArrayList list = new ArrayList();

        ParseContext context = parser.getContext();

        parser.setContext(context, object, fieldInfo.name);
        parseArray(parser, objectType, list);
        parser.setContext(context);

        if (object == null) {
            fieldValues.put(fieldInfo.name, list);
        } else {
            setValue(object, list);
        }
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    public final void parseArray(DefaultJSONParser parser, Type objectType, Collection array) {
        Type itemType = this.itemType;
        ObjectDeserializer itemTypeDeser = this.deserializer;

        if (itemType instanceof TypeVariable //
                && objectType instanceof ParameterizedType) {
            TypeVariable typeVar = (TypeVariable) itemType;
            ParameterizedType paramType = (ParameterizedType) objectType;

            Class<?> objectClass = null;
            if (paramType.getRawType() instanceof Class) {
                objectClass = (Class<?>) paramType.getRawType();
            }

            int paramIndex = -1;
            if (objectClass != null) {
                for (int i = 0, size = objectClass.getTypeParameters().length; i < size; ++i) {
                    TypeVariable item = objectClass.getTypeParameters()[i];
                    if (item.getName().equals(typeVar.getName())) {
                        paramIndex = i;
                        break;
                    }
                }
            }

            if (paramIndex != -1) {
                itemType = paramType.getActualTypeArguments()[paramIndex];
                if (!itemType.equals(this.itemType)) {
                    itemTypeDeser = parser.getConfig().getDeserializer(itemType);
                }
            }
        }

        final JSONLexer lexer = parser.lexer;

        int token = lexer.token();

        if (token == JSONToken.LBRACKET) {
            parseArray(parser, array, itemType, itemTypeDeser, lexer);
        } else {
            if (itemTypeDeser == null) {
                itemTypeDeser = deserializer = parser.getConfig().getDeserializer(itemType);
                itemFastMatchToken = deserializer.getFastMatchToken();
            }
            Object val = itemTypeDeser.deserialze(parser, itemType, 0);
            array.add(val);
            parser.checkListResolve(array);
        }
    }

    private void parseArray(DefaultJSONParser parser, Collection array, Type itemType, ObjectDeserializer itemTypeDeser, JSONLexer lexer) {
        if (itemTypeDeser == null) {
            itemTypeDeser = deserializer = parser.getConfig().getDeserializer(itemType);
            itemFastMatchToken = deserializer.getFastMatchToken();
        }

        lexer.nextToken(itemFastMatchToken);
        for (int i = 0; ; ++i) {
            if (lexer.isEnabled(Feature.AllowArbitraryCommas)) {
                while (lexer.token() == JSONToken.COMMA) {
                    lexer.nextToken();
                    continue;
                }
            }

            if (lexer.token() == JSONToken.RBRACKET) {
                break;
            }

            Object val = itemTypeDeser.deserialze(parser, itemType, i);
            array.add(val);

            parser.checkListResolve(array);

            if (lexer.token() == JSONToken.COMMA) {
                lexer.nextToken(itemFastMatchToken);
                continue;
            }
        }
        lexer.nextToken(JSONToken.COMMA);
    }

}

@@ -706,24 +706,32 @@
  final Type 
+        
 itemType;%0A  
@@ -744,16 +744,31 @@
 ate int 
+               
 itemFast
@@ -925,17 +925,16 @@
 eldInfo)
- 
 %7B%0A      
@@ -2017,16 +2017,17 @@
 rnings(%7B
+ 
 %22uncheck
@@ -2041,16 +2041,17 @@
 awtypes%22
+ 
 %7D)%0A    p
@@ -2303,20 +2303,16 @@
         
-    
 && objec
@@ -3453,19 +3453,11 @@
    i
-nt token = 
+f (
 lexe
@@ -3469,28 +3469,8 @@
 en()
-;%0A%0A        if (token
  == 
@@ -3563,33 +3563,32 @@
 exer);%0A        %7D
- 
 else %7B%0A         
@@ -3716,79 +3716,8 @@
 e);%0A
-                itemFastMatchToken = deserializer.getFastMatchToken();%0A
     
@@ -4268,32 +4268,33 @@
 astMatchToken);%0A
+%0A
         for (int
@@ -4300,17 +4300,16 @@
 t i = 0;
- 
 ; ++i) %7B
@@ -4921,32 +4921,33 @@
     %7D%0A        %7D%0A
+%0A
         lexer.ne

修改 ArrayListTypeFieldDeserializer 将json转换为实体类,当json数组中只有一个对象,没有放到中括弧中此时会报错. 修改后将对象存放到数组的第一个元素中.