Search in sources :

Example 11 with FieldInfo

use of com.alibaba.fastjson.util.FieldInfo in project pinot by linkedin.

the class JSONUtil method toJSON.

@SuppressWarnings("unchecked")
public static Object toJSON(Object javaObject) {
    if (javaObject == null) {
        return null;
    }
    if (javaObject instanceof JSON) {
        return javaObject;
    }
    if (javaObject instanceof FastJSONObject) {
        return ((FastJSONObject) javaObject).getInnerJSONObject();
    }
    if (javaObject instanceof FastJSONArray) {
        return ((FastJSONArray) javaObject).getInnerJSONArray();
    }
    if (javaObject instanceof Map) {
        Map<Object, Object> map = (Map<Object, Object>) javaObject;
        com.alibaba.fastjson.JSONObject json = new com.alibaba.fastjson.JSONObject(map.size());
        for (Map.Entry<Object, Object> entry : map.entrySet()) {
            Object key = entry.getKey();
            String jsonKey = TypeUtils.castToString(key);
            Object jsonValue = toJSON(entry.getValue());
            json.put(jsonKey, jsonValue);
        }
        return json;
    }
    if (javaObject instanceof Collection) {
        Collection<Object> collection = (Collection<Object>) javaObject;
        com.alibaba.fastjson.JSONArray array = new com.alibaba.fastjson.JSONArray(collection.size());
        for (Object item : collection) {
            Object jsonValue = toJSON(item);
            array.add(jsonValue);
        }
        return array;
    }
    Class<?> clazz = javaObject.getClass();
    if (clazz.isEnum()) {
        return ((Enum<?>) javaObject).name();
    }
    if (clazz.isArray()) {
        int len = Array.getLength(javaObject);
        com.alibaba.fastjson.JSONArray array = new com.alibaba.fastjson.JSONArray(len);
        for (int i = 0; i < len; ++i) {
            Object item = Array.get(javaObject, i);
            Object jsonValue = toJSON(item);
            array.add(jsonValue);
        }
        return array;
    }
    if (ParserConfig.getGlobalInstance().isPrimitive(clazz)) {
        return javaObject;
    }
    try {
        List<FieldInfo> getters = TypeUtils.computeGetters(clazz, null);
        com.alibaba.fastjson.JSONObject json = new com.alibaba.fastjson.JSONObject(getters.size());
        for (FieldInfo field : getters) {
            Object value = field.get(javaObject);
            Object jsonValue = toJSON(value);
            json.put(field.getName(), jsonValue);
        }
        return json;
    } catch (Exception e) {
        throw new com.alibaba.fastjson.JSONException("toJSON error", e);
    }
}
Also used : JSONArray(org.json.JSONArray) JSON(com.alibaba.fastjson.JSON) JSONException(org.json.JSONException) JSONObject(org.json.JSONObject) Collection(java.util.Collection) JSONObject(org.json.JSONObject) Map(java.util.Map) FieldInfo(com.alibaba.fastjson.util.FieldInfo)

Example 12 with FieldInfo

use of com.alibaba.fastjson.util.FieldInfo in project QuickAndroid by ImKarl.

the class QAJsonUtils method toJson.

/**
     * 序列化为JSON对象
     *
     * @param javaObject 要序列化的对象
     * @return 三种种可能值:QAJsonObject、QAJsonArray、null
     */
public static QAJson toJson(Object javaObject) {
    if (javaObject == null) {
        return null;
    }
    if (javaObject instanceof JSON) {
        return null;
    }
    if (javaObject instanceof Map) {
        @SuppressWarnings("unchecked") Map<Object, Object> map = (Map<Object, Object>) javaObject;
        QAJsonObject json = new QAJsonObject();
        for (Map.Entry<Object, Object> entry : map.entrySet()) {
            Object key = entry.getKey();
            String jsonKey = TypeUtils.castToString(key);
            Object jsonValue = toJson(entry.getValue());
            json.put(jsonKey, jsonValue);
        }
        return json;
    }
    if (javaObject instanceof Collection) {
        @SuppressWarnings("unchecked") Collection<Object> collection = (Collection<Object>) javaObject;
        QAJsonArray array = new QAJsonArray();
        for (Object item : collection) {
            Object jsonValue = toJson(item);
            array.put(jsonValue);
        }
        return array;
    }
    Class<?> clazz = javaObject.getClass();
    if (clazz.isEnum()) {
        return null;
    }
    if (clazz.isArray()) {
        int len = Array.getLength(javaObject);
        QAJsonArray array = new QAJsonArray();
        for (int i = 0; i < len; ++i) {
            Object item = Array.get(javaObject, i);
            Object jsonValue = toJson(item);
            array.put(jsonValue);
        }
        return array;
    }
    if (ParserConfig.getGlobalInstance().isPrimitive(clazz)) {
        return null;
    }
    try {
        List<FieldInfo> getters = TypeUtils.computeGetters(clazz, null);
        QAJsonObject json = new QAJsonObject();
        for (FieldInfo field : getters) {
            Object value = field.get(javaObject);
            Object jsonValue = toJson(value);
            json.put(field.getName(), jsonValue);
        }
        return json;
    } catch (IllegalAccessException e) {
    } catch (InvocationTargetException e) {
    }
    return null;
}
Also used : JSON(com.alibaba.fastjson.JSON) InvocationTargetException(java.lang.reflect.InvocationTargetException) Collection(java.util.Collection) JSONObject(org.json.JSONObject) Map(java.util.Map) FieldInfo(com.alibaba.fastjson.util.FieldInfo)

Example 13 with FieldInfo

use of com.alibaba.fastjson.util.FieldInfo in project fastjson by alibaba.

the class JavaBeanDeserializer method deserialze.

@SuppressWarnings({ "unchecked", "rawtypes" })
protected <// 
T> // 
T deserialze(// 
DefaultJSONParser parser, // 
Type type, // 
Object fieldName, //
Object object, //
int features, int[] setFlags) {
    if (type == JSON.class || type == JSONObject.class) {
        return (T) parser.parse();
    }
    // xxx
    final JSONLexerBase lexer = (JSONLexerBase) parser.lexer;
    int token = lexer.token();
    if (token == JSONToken.NULL) {
        lexer.nextToken(JSONToken.COMMA);
        return null;
    }
    ParseContext context = parser.getContext();
    if (object != null && context != null) {
        context = context.parent;
    }
    ParseContext childContext = null;
    try {
        Map<String, Object> fieldValues = null;
        if (token == JSONToken.RBRACE) {
            lexer.nextToken(JSONToken.COMMA);
            if (object == null) {
                object = createInstance(parser, type);
            }
            return (T) object;
        }
        if (token == JSONToken.LBRACKET) {
            final int mask = Feature.SupportArrayToBean.mask;
            boolean isSupportArrayToBean = //
            (beanInfo.parserFeatures & mask) != 0 || //
            lexer.isEnabled(Feature.SupportArrayToBean) || (features & mask) != 0;
            if (isSupportArrayToBean) {
                return deserialzeArrayMapping(parser, type, fieldName, object);
            }
        }
        if (token != JSONToken.LBRACE && token != JSONToken.COMMA) {
            if (lexer.isBlankInput()) {
                return null;
            }
            if (token == JSONToken.LITERAL_STRING) {
                String strVal = lexer.stringVal();
                if (strVal.length() == 0) {
                    lexer.nextToken();
                    return null;
                }
            }
            if (token == JSONToken.LBRACKET && lexer.getCurrent() == ']') {
                lexer.next();
                lexer.nextToken();
                return null;
            }
            StringBuffer buf = //
            (new StringBuffer()).append(//
            "syntax error, expect {, actual ").append(//
            lexer.tokenName()).append(//
            ", pos ").append(//
            lexer.pos());
            if (fieldName instanceof String) {
                //
                buf.append(//
                ", fieldName ").append(fieldName);
            }
            throw new JSONException(buf.toString());
        }
        if (parser.resolveStatus == DefaultJSONParser.TypeNameRedirect) {
            parser.resolveStatus = DefaultJSONParser.NONE;
        }
        for (int fieldIndex = 0; ; fieldIndex++) {
            String key = null;
            FieldDeserializer fieldDeser = null;
            FieldInfo fieldInfo = null;
            Class<?> fieldClass = null;
            JSONField feildAnnotation = null;
            if (fieldIndex < sortedFieldDeserializers.length) {
                fieldDeser = sortedFieldDeserializers[fieldIndex];
                fieldInfo = fieldDeser.fieldInfo;
                fieldClass = fieldInfo.fieldClass;
                feildAnnotation = fieldInfo.getAnnotation();
            }
            boolean matchField = false;
            boolean valueParsed = false;
            Object fieldValue = null;
            if (fieldDeser != null) {
                char[] name_chars = fieldInfo.name_chars;
                if (fieldClass == int.class || fieldClass == Integer.class) {
                    fieldValue = lexer.scanFieldInt(name_chars);
                    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);
                    if (lexer.matchStat > 0) {
                        matchField = true;
                        valueParsed = true;
                    } else if (lexer.matchStat == JSONLexer.NOT_MATCH_NAME) {
                        continue;
                    }
                } else if (fieldClass == String.class) {
                    fieldValue = lexer.scanFieldString(name_chars);
                    if (lexer.matchStat > 0) {
                        matchField = true;
                        valueParsed = true;
                    } else if (lexer.matchStat == JSONLexer.NOT_MATCH_NAME) {
                        continue;
                    }
                } else if (fieldClass == boolean.class || fieldClass == Boolean.class) {
                    fieldValue = lexer.scanFieldBoolean(name_chars);
                    if (lexer.matchStat > 0) {
                        matchField = true;
                        valueParsed = true;
                    } else if (lexer.matchStat == JSONLexer.NOT_MATCH_NAME) {
                        continue;
                    }
                } else if (fieldClass == float.class || fieldClass == Float.class) {
                    fieldValue = lexer.scanFieldFloat(name_chars);
                    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);
                    if (lexer.matchStat > 0) {
                        matchField = true;
                        valueParsed = true;
                    } else if (lexer.matchStat == JSONLexer.NOT_MATCH_NAME) {
                        continue;
                    }
                } else if (// 
                fieldClass.isEnum() && parser.getConfig().getDeserializer(fieldClass) instanceof EnumDeserializer && (feildAnnotation == null || feildAnnotation.deserializeUsing() == Void.class)) {
                    if (fieldDeser instanceof DefaultFieldDeserializer) {
                        ObjectDeserializer fieldValueDeserilizer = ((DefaultFieldDeserializer) fieldDeser).fieldValueDeserilizer;
                        fieldValue = this.scanEnum(lexer, name_chars, fieldValueDeserilizer);
                        if (lexer.matchStat > 0) {
                            matchField = true;
                            valueParsed = true;
                        } else if (lexer.matchStat == JSONLexer.NOT_MATCH_NAME) {
                            continue;
                        }
                    }
                } else if (fieldClass == int[].class) {
                    fieldValue = lexer.scanFieldIntArray(name_chars);
                    if (lexer.matchStat > 0) {
                        matchField = true;
                        valueParsed = true;
                    } else if (lexer.matchStat == JSONLexer.NOT_MATCH_NAME) {
                        continue;
                    }
                } else if (fieldClass == float[].class) {
                    fieldValue = lexer.scanFieldFloatArray(name_chars);
                    if (lexer.matchStat > 0) {
                        matchField = true;
                        valueParsed = true;
                    } else if (lexer.matchStat == JSONLexer.NOT_MATCH_NAME) {
                        continue;
                    }
                } else if (fieldClass == float[][].class) {
                    fieldValue = lexer.scanFieldFloatArray2(name_chars);
                    if (lexer.matchStat > 0) {
                        matchField = true;
                        valueParsed = true;
                    } else if (lexer.matchStat == JSONLexer.NOT_MATCH_NAME) {
                        continue;
                    }
                } else if (lexer.matchField(name_chars)) {
                    matchField = true;
                } else {
                    continue;
                }
            }
            if (!matchField) {
                key = lexer.scanSymbol(parser.symbolTable);
                if (key == null) {
                    token = lexer.token();
                    if (token == JSONToken.RBRACE) {
                        lexer.nextToken(JSONToken.COMMA);
                        break;
                    }
                    if (token == JSONToken.COMMA) {
                        if (lexer.isEnabled(Feature.AllowArbitraryCommas)) {
                            continue;
                        }
                    }
                }
                if ("$ref" == key) {
                    lexer.nextTokenWithColon(JSONToken.LITERAL_STRING);
                    token = lexer.token();
                    if (token == JSONToken.LITERAL_STRING) {
                        String ref = lexer.stringVal();
                        if ("@".equals(ref)) {
                            object = context.object;
                        } else if ("..".equals(ref)) {
                            ParseContext parentContext = context.parent;
                            if (parentContext.object != null) {
                                object = parentContext.object;
                            } else {
                                parser.addResolveTask(new ResolveTask(parentContext, ref));
                                parser.resolveStatus = DefaultJSONParser.NeedToResolve;
                            }
                        } else if ("$".equals(ref)) {
                            ParseContext rootContext = context;
                            while (rootContext.parent != null) {
                                rootContext = rootContext.parent;
                            }
                            if (rootContext.object != null) {
                                object = rootContext.object;
                            } else {
                                parser.addResolveTask(new ResolveTask(rootContext, ref));
                                parser.resolveStatus = DefaultJSONParser.NeedToResolve;
                            }
                        } else {
                            parser.addResolveTask(new ResolveTask(context, ref));
                            parser.resolveStatus = DefaultJSONParser.NeedToResolve;
                        }
                    } else {
                        throw new JSONException("illegal ref, " + JSONToken.name(token));
                    }
                    lexer.nextToken(JSONToken.RBRACE);
                    if (lexer.token() != JSONToken.RBRACE) {
                        throw new JSONException("illegal ref");
                    }
                    lexer.nextToken(JSONToken.COMMA);
                    parser.setContext(context, object, fieldName);
                    return (T) object;
                }
                if (JSON.DEFAULT_TYPE_KEY == key) {
                    lexer.nextTokenWithColon(JSONToken.LITERAL_STRING);
                    if (lexer.token() == JSONToken.LITERAL_STRING) {
                        String typeName = lexer.stringVal();
                        lexer.nextToken(JSONToken.COMMA);
                        if (typeName.equals(beanInfo.typeName) || parser.isEnabled(Feature.IgnoreAutoType)) {
                            if (lexer.token() == JSONToken.RBRACE) {
                                lexer.nextToken();
                                break;
                            }
                            continue;
                        }
                        ParserConfig config = parser.getConfig();
                        ObjectDeserializer deserializer = getSeeAlso(config, this.beanInfo, typeName);
                        Class<?> userType = null;
                        if (deserializer == null) {
                            Class<?> expectClass = TypeUtils.getClass(type);
                            userType = config.checkAutoType(typeName, expectClass);
                            deserializer = parser.getConfig().getDeserializer(userType);
                        }
                        return (T) deserializer.deserialze(parser, userType, fieldName);
                    } else {
                        throw new JSONException("syntax error");
                    }
                }
            }
            if (object == null && fieldValues == null) {
                object = createInstance(parser, type);
                if (object == null) {
                    fieldValues = new HashMap<String, Object>(this.fieldDeserializers.length);
                }
                childContext = parser.setContext(context, object, fieldName);
            }
            if (matchField) {
                if (!valueParsed) {
                    fieldDeser.parseField(parser, object, type, fieldValues);
                } else {
                    if (object == null) {
                        fieldValues.put(fieldInfo.name, fieldValue);
                    } else if (fieldValue == null) {
                        if (//
                        fieldClass != int.class && //
                        fieldClass != long.class && //
                        fieldClass != float.class && //
                        fieldClass != double.class && //
                        fieldClass != boolean.class) {
                            fieldDeser.setValue(object, fieldValue);
                        }
                    } else {
                        fieldDeser.setValue(object, fieldValue);
                    }
                    if (lexer.matchStat == JSONLexer.END) {
                        break;
                    }
                }
            } else {
                boolean match = parseField(parser, key, object, type, fieldValues, setFlags);
                if (!match) {
                    if (lexer.token() == JSONToken.RBRACE) {
                        lexer.nextToken();
                        break;
                    }
                    continue;
                } else if (lexer.token() == JSONToken.COLON) {
                    throw new JSONException("syntax error, unexpect token ':'");
                }
            }
            if (lexer.token() == JSONToken.COMMA) {
                continue;
            }
            if (lexer.token() == JSONToken.RBRACE) {
                lexer.nextToken(JSONToken.COMMA);
                break;
            }
            if (lexer.token() == JSONToken.IDENTIFIER || lexer.token() == JSONToken.ERROR) {
                throw new JSONException("syntax error, unexpect token " + JSONToken.name(lexer.token()));
            }
        }
        if (object == null) {
            if (fieldValues == null) {
                object = createInstance(parser, type);
                if (childContext == null) {
                    childContext = parser.setContext(context, object, fieldName);
                }
                return (T) object;
            }
            FieldInfo[] fieldInfoList = beanInfo.fields;
            int size = fieldInfoList.length;
            Object[] params = new Object[size];
            for (int i = 0; i < size; ++i) {
                FieldInfo fieldInfo = fieldInfoList[i];
                Object param = fieldValues.get(fieldInfo.name);
                if (param == null) {
                    Type fieldType = fieldInfo.fieldType;
                    if (fieldType == byte.class) {
                        param = (byte) 0;
                    } else if (fieldType == short.class) {
                        param = (short) 0;
                    } else if (fieldType == int.class) {
                        param = 0;
                    } else if (fieldType == long.class) {
                        param = 0L;
                    } else if (fieldType == float.class) {
                        param = 0F;
                    } else if (fieldType == double.class) {
                        param = 0D;
                    } else if (fieldType == boolean.class) {
                        param = Boolean.FALSE;
                    }
                }
                params[i] = param;
            }
            if (beanInfo.creatorConstructor != null) {
                try {
                    object = beanInfo.creatorConstructor.newInstance(params);
                } catch (Exception e) {
                    throw new JSONException("create instance error, " + beanInfo.creatorConstructor.toGenericString(), e);
                }
            } else if (beanInfo.factoryMethod != null) {
                try {
                    object = beanInfo.factoryMethod.invoke(null, params);
                } catch (Exception e) {
                    throw new JSONException("create factory method error, " + beanInfo.factoryMethod.toString(), e);
                }
            }
        }
        Method buildMethod = beanInfo.buildMethod;
        if (buildMethod == null) {
            return (T) object;
        }
        Object builtObj;
        try {
            builtObj = buildMethod.invoke(object);
        } catch (Exception e) {
            throw new JSONException("build object error", e);
        }
        return (T) builtObj;
    } finally {
        if (childContext != null) {
            childContext.object = object;
        }
        parser.setContext(context);
    }
}
Also used : JSONField(com.alibaba.fastjson.annotation.JSONField) JSON(com.alibaba.fastjson.JSON) JSONLexerBase(com.alibaba.fastjson.parser.JSONLexerBase) JSONException(com.alibaba.fastjson.JSONException) JSONException(com.alibaba.fastjson.JSONException) JSONObject(com.alibaba.fastjson.JSONObject) ParseContext(com.alibaba.fastjson.parser.ParseContext) JSONObject(com.alibaba.fastjson.JSONObject) FieldInfo(com.alibaba.fastjson.util.FieldInfo) ParserConfig(com.alibaba.fastjson.parser.ParserConfig) ResolveTask(com.alibaba.fastjson.parser.DefaultJSONParser.ResolveTask)

Example 14 with FieldInfo

use of com.alibaba.fastjson.util.FieldInfo in project fastjson by alibaba.

the class JavaBeanDeserializer method createInstance.

public Object createInstance(DefaultJSONParser parser, Type type) {
    if (type instanceof Class) {
        if (clazz.isInterface()) {
            Class<?> clazz = (Class<?>) type;
            ClassLoader loader = Thread.currentThread().getContextClassLoader();
            final JSONObject obj = new JSONObject();
            Object proxy = Proxy.newProxyInstance(loader, new Class<?>[] { clazz }, obj);
            return proxy;
        }
    }
    if (beanInfo.defaultConstructor == null) {
        return null;
    }
    Object object;
    try {
        Constructor<?> constructor = beanInfo.defaultConstructor;
        if (beanInfo.defaultConstructorParameterSize == 0) {
            object = constructor.newInstance();
        } else {
            ParseContext context = parser.getContext();
            if (context == null || context.object == null) {
                throw new JSONException("can't create non-static inner class instance.");
            }
            String parentName = context.object.getClass().getName();
            String typeName = "";
            if (type instanceof Class) {
                typeName = ((Class<?>) type).getName();
            }
            if (parentName.length() != typeName.lastIndexOf('$') - 1) {
                char[] typeChars = typeName.toCharArray();
                StringBuilder clsNameBuilder = new StringBuilder();
                clsNameBuilder.append(parentName).append("$");
                Map<String, Object> outterCached = new HashMap<String, Object>();
                //outtest
                outterCached.put(parentName, context.object);
                for (int i = parentName.length() + 1; i <= typeName.lastIndexOf('$'); i++) {
                    char thisChar = typeChars[i];
                    if (thisChar == '$') {
                        String clsName = clsNameBuilder.toString();
                        Object outter = outterCached.get(parentName);
                        Class<?> clazz;
                        try {
                            clazz = Class.forName(parentName);
                            if (outter != null) {
                                Class<?> innerCls = Class.forName(clsName);
                                Constructor<?> innerClsConstructor = innerCls.getDeclaredConstructor(clazz);
                                if (!innerClsConstructor.isAccessible()) {
                                    innerClsConstructor.setAccessible(true);
                                }
                                Object inner = innerClsConstructor.newInstance(outter);
                                outterCached.put(clsName, inner);
                                parentName = clsName;
                            }
                        } catch (ClassNotFoundException e) {
                            throw new JSONException("unable to find class " + parentName);
                        } catch (NoSuchMethodException e) {
                            // no default contrutor
                            throw new RuntimeException(e);
                        } catch (InvocationTargetException e) {
                            throw new RuntimeException("can not instantiate " + clsName);
                        } catch (IllegalAccessException e) {
                            throw new RuntimeException(e);
                        } catch (InstantiationException e) {
                            throw new RuntimeException(e);
                        }
                    }
                    clsNameBuilder.append(thisChar);
                }
                object = constructor.newInstance(outterCached.get(parentName));
            } else {
                object = constructor.newInstance(context.object);
            }
        }
    } catch (Exception e) {
        throw new JSONException("create instance error, class " + clazz.getName(), e);
    }
    if (// 
    parser != null && parser.lexer.isEnabled(Feature.InitStringFieldAsEmpty)) {
        for (FieldInfo fieldInfo : beanInfo.fields) {
            if (fieldInfo.fieldClass == String.class) {
                try {
                    fieldInfo.set(object, "");
                } catch (Exception e) {
                    throw new JSONException("create instance error, class " + clazz.getName(), e);
                }
            }
        }
    }
    return object;
}
Also used : ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) HashMap(java.util.HashMap) JSONException(com.alibaba.fastjson.JSONException) JSONException(com.alibaba.fastjson.JSONException) JSONObject(com.alibaba.fastjson.JSONObject) ParseContext(com.alibaba.fastjson.parser.ParseContext) JSONObject(com.alibaba.fastjson.JSONObject) FieldInfo(com.alibaba.fastjson.util.FieldInfo)

Example 15 with FieldInfo

use of com.alibaba.fastjson.util.FieldInfo in project fastjson by alibaba.

the class ASMSerializerFactory method createJavaBeanSerializer.

public JavaBeanSerializer createJavaBeanSerializer(SerializeBeanInfo beanInfo) throws Exception {
    Class<?> clazz = beanInfo.beanType;
    if (clazz.isPrimitive()) {
        throw new JSONException("unsupportd class " + clazz.getName());
    }
    JSONType jsonType = clazz.getAnnotation(JSONType.class);
    FieldInfo[] unsortedGetters = beanInfo.fields;
    ;
    for (FieldInfo fieldInfo : unsortedGetters) {
        if (//
        fieldInfo.field == null && //
        fieldInfo.method != null && fieldInfo.method.getDeclaringClass().isInterface()) {
            return new JavaBeanSerializer(clazz);
        }
    }
    FieldInfo[] getters = beanInfo.sortedFields;
    boolean nativeSorted = beanInfo.sortedFields == beanInfo.fields;
    if (getters.length > 256) {
        return new JavaBeanSerializer(clazz);
    }
    for (FieldInfo getter : getters) {
        if (!ASMUtils.checkName(getter.getMember().getName())) {
            return new JavaBeanSerializer(clazz);
        }
    }
    String className = "ASMSerializer_" + seed.incrementAndGet() + "_" + clazz.getSimpleName();
    String packageName = ASMSerializerFactory.class.getPackage().getName();
    String classNameType = packageName.replace('.', '/') + "/" + className;
    String classNameFull = packageName + "." + className;
    ClassWriter cw = new ClassWriter();
    //
    cw.visit(//
    V1_5, //
    ACC_PUBLIC + ACC_SUPER, //
    classNameType, //
    JavaBeanSerializer, //
    new String[] { ObjectSerializer });
    for (FieldInfo fieldInfo : getters) {
        if (//
        fieldInfo.fieldClass.isPrimitive() || //|| fieldInfo.fieldClass.isEnum() //
        fieldInfo.fieldClass == String.class) {
            continue;
        }
        //
        new FieldWriter(cw, ACC_PUBLIC, fieldInfo.name + "_asm_fieldType", "Ljava/lang/reflect/Type;").visitEnd();
        if (List.class.isAssignableFrom(fieldInfo.fieldClass)) {
            new FieldWriter(cw, ACC_PUBLIC, fieldInfo.name + "_asm_list_item_ser_", //
            ObjectSerializer_desc).visitEnd();
        }
        //
        new FieldWriter(cw, ACC_PUBLIC, fieldInfo.name + "_asm_ser_", ObjectSerializer_desc).visitEnd();
    }
    MethodVisitor mw = new MethodWriter(cw, ACC_PUBLIC, "<init>", "(" + desc(SerializeBeanInfo.class) + ")V", null, null);
    mw.visitVarInsn(ALOAD, 0);
    mw.visitVarInsn(ALOAD, 1);
    mw.visitMethodInsn(INVOKESPECIAL, JavaBeanSerializer, "<init>", "(" + desc(SerializeBeanInfo.class) + ")V");
    // init _asm_fieldType
    for (int i = 0; i < getters.length; ++i) {
        FieldInfo fieldInfo = getters[i];
        if (//
        fieldInfo.fieldClass.isPrimitive() || //                || fieldInfo.fieldClass.isEnum() //
        fieldInfo.fieldClass == String.class) {
            continue;
        }
        mw.visitVarInsn(ALOAD, 0);
        if (fieldInfo.method != null) {
            mw.visitLdcInsn(com.alibaba.fastjson.asm.Type.getType(desc(fieldInfo.declaringClass)));
            mw.visitLdcInsn(fieldInfo.method.getName());
            mw.visitMethodInsn(INVOKESTATIC, type(ASMUtils.class), "getMethodType", "(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/reflect/Type;");
        } else {
            mw.visitVarInsn(ALOAD, 0);
            mw.visitLdcInsn(i);
            mw.visitMethodInsn(INVOKESPECIAL, JavaBeanSerializer, "getFieldType", "(I)Ljava/lang/reflect/Type;");
        }
        mw.visitFieldInsn(PUTFIELD, classNameType, fieldInfo.name + "_asm_fieldType", "Ljava/lang/reflect/Type;");
    }
    mw.visitInsn(RETURN);
    mw.visitMaxs(4, 4);
    mw.visitEnd();
    boolean DisableCircularReferenceDetect = false;
    if (jsonType != null) {
        for (SerializerFeature featrues : jsonType.serialzeFeatures()) {
            if (featrues == SerializerFeature.DisableCircularReferenceDetect) {
                DisableCircularReferenceDetect = true;
                break;
            }
        }
    }
    // 2 writeNonContext
    for (int i = 0; i < 3; ++i) {
        String methodName;
        boolean nonContext = DisableCircularReferenceDetect;
        boolean writeDirect = false;
        if (i == 0) {
            methodName = "write";
            writeDirect = true;
        } else if (i == 1) {
            methodName = "writeNormal";
        } else {
            writeDirect = true;
            nonContext = true;
            methodName = "writeDirectNonContext";
        }
        Context context = new Context(getters, beanInfo, classNameType, writeDirect, nonContext);
        mw = new //
        MethodWriter(//
        cw, //
        ACC_PUBLIC, //
        methodName, "(L" + JSONSerializer + //
        ";Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/reflect/Type;I)V", //
        null, //
        new String[] { "java/io/IOException" });
        {
            Label endIf_ = new Label();
            mw.visitVarInsn(ALOAD, Context.obj);
            //serializer.writeNull();
            mw.visitJumpInsn(IFNONNULL, endIf_);
            mw.visitVarInsn(ALOAD, Context.serializer);
            mw.visitMethodInsn(INVOKEVIRTUAL, JSONSerializer, "writeNull", "()V");
            mw.visitInsn(RETURN);
            mw.visitLabel(endIf_);
        }
        mw.visitVarInsn(ALOAD, Context.serializer);
        mw.visitFieldInsn(GETFIELD, JSONSerializer, "out", SerializeWriter_desc);
        mw.visitVarInsn(ASTORE, context.var("out"));
        if (//
        (!nativeSorted) && !context.writeDirect) {
            if (jsonType == null || jsonType.alphabetic()) {
                Label _else = new Label();
                mw.visitVarInsn(ALOAD, context.var("out"));
                mw.visitMethodInsn(INVOKEVIRTUAL, SerializeWriter, "isSortField", "()Z");
                mw.visitJumpInsn(IFNE, _else);
                mw.visitVarInsn(ALOAD, 0);
                mw.visitVarInsn(ALOAD, 1);
                mw.visitVarInsn(ALOAD, 2);
                mw.visitVarInsn(ALOAD, 3);
                mw.visitVarInsn(ALOAD, 4);
                mw.visitVarInsn(ILOAD, 5);
                mw.visitMethodInsn(INVOKEVIRTUAL, classNameType, "writeUnsorted", "(L" + JSONSerializer + ";Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/reflect/Type;I)V");
                mw.visitInsn(RETURN);
                mw.visitLabel(_else);
            }
        }
        // isWriteDoubleQuoteDirect
        if (context.writeDirect && !nonContext) {
            Label _direct = new Label();
            Label _directElse = new Label();
            mw.visitVarInsn(ALOAD, 0);
            mw.visitVarInsn(ALOAD, Context.serializer);
            mw.visitMethodInsn(INVOKEVIRTUAL, JavaBeanSerializer, "writeDirect", "(L" + JSONSerializer + ";)Z");
            mw.visitJumpInsn(IFNE, _directElse);
            mw.visitVarInsn(ALOAD, 0);
            mw.visitVarInsn(ALOAD, 1);
            mw.visitVarInsn(ALOAD, 2);
            mw.visitVarInsn(ALOAD, 3);
            mw.visitVarInsn(ALOAD, 4);
            mw.visitVarInsn(ILOAD, 5);
            mw.visitMethodInsn(INVOKEVIRTUAL, classNameType, "writeNormal", "(L" + JSONSerializer + ";Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/reflect/Type;I)V");
            mw.visitInsn(RETURN);
            mw.visitLabel(_directElse);
            mw.visitVarInsn(ALOAD, context.var("out"));
            mw.visitLdcInsn(SerializerFeature.DisableCircularReferenceDetect.mask);
            mw.visitMethodInsn(INVOKEVIRTUAL, SerializeWriter, "isEnabled", "(I)Z");
            mw.visitJumpInsn(IFEQ, _direct);
            mw.visitVarInsn(ALOAD, 0);
            mw.visitVarInsn(ALOAD, 1);
            mw.visitVarInsn(ALOAD, 2);
            mw.visitVarInsn(ALOAD, 3);
            mw.visitVarInsn(ALOAD, 4);
            mw.visitVarInsn(ILOAD, 5);
            mw.visitMethodInsn(INVOKEVIRTUAL, classNameType, "writeDirectNonContext", "(L" + JSONSerializer + ";Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/reflect/Type;I)V");
            mw.visitInsn(RETURN);
            mw.visitLabel(_direct);
        }
        // obj
        mw.visitVarInsn(ALOAD, Context.obj);
        // serializer
        mw.visitTypeInsn(CHECKCAST, type(clazz));
        // obj
        mw.visitVarInsn(ASTORE, context.var("entity"));
        generateWriteMethod(clazz, mw, getters, context);
        mw.visitInsn(RETURN);
        mw.visitMaxs(7, context.variantIndex + 2);
        mw.visitEnd();
    }
    if (!nativeSorted) {
        // sortField support
        Context context = new Context(getters, beanInfo, classNameType, false, DisableCircularReferenceDetect);
        mw = new MethodWriter(cw, ACC_PUBLIC, "writeUnsorted", "(L" + JSONSerializer + ";Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/reflect/Type;I)V", null, new String[] { "java/io/IOException" });
        mw.visitVarInsn(ALOAD, Context.serializer);
        mw.visitFieldInsn(GETFIELD, JSONSerializer, "out", SerializeWriter_desc);
        mw.visitVarInsn(ASTORE, context.var("out"));
        // obj
        mw.visitVarInsn(ALOAD, Context.obj);
        // serializer
        mw.visitTypeInsn(CHECKCAST, type(clazz));
        // obj
        mw.visitVarInsn(ASTORE, context.var("entity"));
        generateWriteMethod(clazz, mw, unsortedGetters, context);
        mw.visitInsn(RETURN);
        mw.visitMaxs(7, context.variantIndex + 2);
        mw.visitEnd();
    }
    // 2 writeAsArrayNonContext
    for (int i = 0; i < 3; ++i) {
        String methodName;
        boolean nonContext = DisableCircularReferenceDetect;
        boolean writeDirect = false;
        if (i == 0) {
            methodName = "writeAsArray";
            writeDirect = true;
        } else if (i == 1) {
            methodName = "writeAsArrayNormal";
        } else {
            writeDirect = true;
            nonContext = true;
            methodName = "writeAsArrayNonContext";
        }
        Context context = new Context(getters, beanInfo, classNameType, writeDirect, nonContext);
        mw = new MethodWriter(cw, ACC_PUBLIC, methodName, "(L" + JSONSerializer + ";Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/reflect/Type;I)V", null, new String[] { "java/io/IOException" });
        mw.visitVarInsn(ALOAD, Context.serializer);
        mw.visitFieldInsn(GETFIELD, JSONSerializer, "out", SerializeWriter_desc);
        mw.visitVarInsn(ASTORE, context.var("out"));
        // obj
        mw.visitVarInsn(ALOAD, Context.obj);
        // serializer
        mw.visitTypeInsn(CHECKCAST, type(clazz));
        // obj
        mw.visitVarInsn(ASTORE, context.var("entity"));
        generateWriteAsArray(clazz, mw, getters, context);
        mw.visitInsn(RETURN);
        mw.visitMaxs(7, context.variantIndex + 2);
        mw.visitEnd();
    }
    byte[] code = cw.toByteArray();
    Class<?> exampleClass = classLoader.defineClassPublic(classNameFull, code, 0, code.length);
    Constructor<?> constructor = exampleClass.getConstructor(SerializeBeanInfo.class);
    Object instance = constructor.newInstance(beanInfo);
    return (JavaBeanSerializer) instance;
}
Also used : MethodWriter(com.alibaba.fastjson.asm.MethodWriter) Label(com.alibaba.fastjson.asm.Label) JSONException(com.alibaba.fastjson.JSONException) ASMUtils(com.alibaba.fastjson.util.ASMUtils) ClassWriter(com.alibaba.fastjson.asm.ClassWriter) FieldWriter(com.alibaba.fastjson.asm.FieldWriter) MethodVisitor(com.alibaba.fastjson.asm.MethodVisitor) JSONType(com.alibaba.fastjson.annotation.JSONType) FieldInfo(com.alibaba.fastjson.util.FieldInfo)

Aggregations

FieldInfo (com.alibaba.fastjson.util.FieldInfo)20 JSONException (com.alibaba.fastjson.JSONException)7 Label (com.alibaba.fastjson.asm.Label)6 JSONObject (com.alibaba.fastjson.JSONObject)4 JSONField (com.alibaba.fastjson.annotation.JSONField)4 MethodVisitor (com.alibaba.fastjson.asm.MethodVisitor)4 MethodWriter (com.alibaba.fastjson.asm.MethodWriter)4 Type (java.lang.reflect.Type)4 JSON (com.alibaba.fastjson.JSON)3 JSONType (com.alibaba.fastjson.annotation.JSONType)3 ParseContext (com.alibaba.fastjson.parser.ParseContext)3 Field (java.lang.reflect.Field)3 Method (java.lang.reflect.Method)3 ParameterizedType (java.lang.reflect.ParameterizedType)3 Collection (java.util.Collection)3 Map (java.util.Map)3 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)3 FieldWriter (com.alibaba.fastjson.asm.FieldWriter)2 JavaBeanInfo (com.alibaba.fastjson.util.JavaBeanInfo)2 InvocationTargetException (java.lang.reflect.InvocationTargetException)2