Search in sources :

Example 11 with JSONType

use of com.alibaba.fastjson.annotation.JSONType in project fastjson by alibaba.

the class ParserConfig method createJavaBeanDeserializer.

public ObjectDeserializer createJavaBeanDeserializer(Class<?> clazz, Type type) {
    boolean asmEnable = this.asmEnable & !this.fieldBased;
    if (asmEnable) {
        JSONType jsonType = TypeUtils.getAnnotation(clazz, JSONType.class);
        if (jsonType != null) {
            Class<?> deserializerClass = jsonType.deserializer();
            if (deserializerClass != Void.class) {
                try {
                    Object deseralizer = deserializerClass.newInstance();
                    if (deseralizer instanceof ObjectDeserializer) {
                        return (ObjectDeserializer) deseralizer;
                    }
                } catch (Throwable e) {
                // skip
                }
            }
            asmEnable = jsonType.asm() && jsonType.parseFeatures().length == 0;
        }
        if (asmEnable) {
            Class<?> superClass = JavaBeanInfo.getBuilderClass(clazz, jsonType);
            if (superClass == null) {
                superClass = clazz;
            }
            for (; ; ) {
                if (!Modifier.isPublic(superClass.getModifiers())) {
                    asmEnable = false;
                    break;
                }
                superClass = superClass.getSuperclass();
                if (superClass == Object.class || superClass == null) {
                    break;
                }
            }
        }
    }
    if (clazz.getTypeParameters().length != 0) {
        asmEnable = false;
    }
    if (asmEnable && asmFactory != null && asmFactory.classLoader.isExternalClass(clazz)) {
        asmEnable = false;
    }
    if (asmEnable) {
        asmEnable = ASMUtils.checkName(clazz.getSimpleName());
    }
    if (asmEnable) {
        if (clazz.isInterface()) {
            asmEnable = false;
        }
        JavaBeanInfo beanInfo = JavaBeanInfo.build(clazz, type, propertyNamingStrategy, false, TypeUtils.compatibleWithJavaBean, jacksonCompatible);
        if (asmEnable && beanInfo.fields.length > 200) {
            asmEnable = false;
        }
        Constructor<?> defaultConstructor = beanInfo.defaultConstructor;
        if (asmEnable && defaultConstructor == null && !clazz.isInterface()) {
            asmEnable = false;
        }
        for (FieldInfo fieldInfo : beanInfo.fields) {
            if (fieldInfo.getOnly) {
                asmEnable = false;
                break;
            }
            Class<?> fieldClass = fieldInfo.fieldClass;
            if (!Modifier.isPublic(fieldClass.getModifiers())) {
                asmEnable = false;
                break;
            }
            if (fieldClass.isMemberClass() && !Modifier.isStatic(fieldClass.getModifiers())) {
                asmEnable = false;
                break;
            }
            if (// 
            fieldInfo.getMember() != null && !ASMUtils.checkName(fieldInfo.getMember().getName())) {
                asmEnable = false;
                break;
            }
            JSONField annotation = fieldInfo.getAnnotation();
            if (// 
            annotation != null && (// 
            (!ASMUtils.checkName(annotation.name())) || // 
            annotation.format().length() != 0 || // 
            annotation.deserializeUsing() != Void.class || // 
            annotation.parseFeatures().length != 0 || annotation.unwrapped()) || (fieldInfo.method != null && fieldInfo.method.getParameterTypes().length > 1)) {
                asmEnable = false;
                break;
            }
            if (fieldClass.isEnum()) {
                // EnumDeserializer
                ObjectDeserializer fieldDeser = this.getDeserializer(fieldClass);
                if (!(fieldDeser instanceof EnumDeserializer)) {
                    asmEnable = false;
                    break;
                }
            }
        }
    }
    if (asmEnable) {
        if (clazz.isMemberClass() && !Modifier.isStatic(clazz.getModifiers())) {
            asmEnable = false;
        }
    }
    if (asmEnable) {
        if (TypeUtils.isXmlField(clazz)) {
            asmEnable = false;
        }
    }
    if (!asmEnable) {
        return new JavaBeanDeserializer(this, clazz, type);
    }
    JavaBeanInfo beanInfo = JavaBeanInfo.build(clazz, type, propertyNamingStrategy);
    try {
        return asmFactory.createJavaBeanDeserializer(this, beanInfo);
    // } catch (VerifyError e) {
    // e.printStackTrace();
    // return new JavaBeanDeserializer(this, clazz, type);
    } catch (NoSuchMethodException ex) {
        return new JavaBeanDeserializer(this, clazz, type);
    } catch (JSONException asmError) {
        return new JavaBeanDeserializer(this, beanInfo);
    } catch (Exception e) {
        throw new JSONException("create asm deserializer error, " + clazz.getName(), e);
    }
}
Also used : JSONField(com.alibaba.fastjson.annotation.JSONField) AccessControlException(java.security.AccessControlException) JSONType(com.alibaba.fastjson.annotation.JSONType)

Example 12 with JSONType

use of com.alibaba.fastjson.annotation.JSONType in project fastjson by alibaba.

the class ASMSerializerFactory method _if_write_null.

private void _if_write_null(MethodVisitor mw, FieldInfo fieldInfo, Context context) {
    Class<?> propertyClass = fieldInfo.fieldClass;
    Label _if = new Label();
    Label _else = new Label();
    Label _write_null = new Label();
    Label _end_if = new Label();
    mw.visitLabel(_if);
    JSONField annotation = fieldInfo.getAnnotation();
    int features = 0;
    if (annotation != null) {
        features = SerializerFeature.of(annotation.serialzeFeatures());
    }
    JSONType jsonType = context.beanInfo.jsonType;
    if (jsonType != null) {
        features |= SerializerFeature.of(jsonType.serialzeFeatures());
    }
    int writeNullFeatures;
    if (propertyClass == String.class) {
        writeNullFeatures = SerializerFeature.WriteMapNullValue.getMask() | SerializerFeature.WriteNullStringAsEmpty.getMask();
    } else if (Number.class.isAssignableFrom(propertyClass)) {
        writeNullFeatures = SerializerFeature.WriteMapNullValue.getMask() | SerializerFeature.WriteNullNumberAsZero.getMask();
    } else if (Collection.class.isAssignableFrom(propertyClass)) {
        writeNullFeatures = SerializerFeature.WriteMapNullValue.getMask() | SerializerFeature.WriteNullListAsEmpty.getMask();
    } else if (Boolean.class == propertyClass) {
        writeNullFeatures = SerializerFeature.WriteMapNullValue.getMask() | SerializerFeature.WriteNullBooleanAsFalse.getMask();
    } else {
        writeNullFeatures = SerializerFeature.WRITE_MAP_NULL_FEATURES;
    }
    if ((features & writeNullFeatures) == 0) {
        mw.visitVarInsn(ALOAD, context.var("out"));
        mw.visitLdcInsn(writeNullFeatures);
        mw.visitMethodInsn(INVOKEVIRTUAL, SerializeWriter, "isEnabled", "(I)Z");
        mw.visitJumpInsn(IFEQ, _else);
    }
    mw.visitLabel(_write_null);
    mw.visitVarInsn(ALOAD, context.var("out"));
    mw.visitVarInsn(ILOAD, context.var("seperator"));
    mw.visitMethodInsn(INVOKEVIRTUAL, SerializeWriter, "write", "(I)V");
    _writeFieldName(mw, context);
    mw.visitVarInsn(ALOAD, context.var("out"));
    mw.visitLdcInsn(features);
    if (propertyClass == String.class || propertyClass == Character.class) {
        mw.visitLdcInsn(SerializerFeature.WriteNullStringAsEmpty.mask);
    } else if (Number.class.isAssignableFrom(propertyClass)) {
        mw.visitLdcInsn(SerializerFeature.WriteNullNumberAsZero.mask);
    } else if (propertyClass == Boolean.class) {
        mw.visitLdcInsn(SerializerFeature.WriteNullBooleanAsFalse.mask);
    } else if (Collection.class.isAssignableFrom(propertyClass) || propertyClass.isArray()) {
        mw.visitLdcInsn(SerializerFeature.WriteNullListAsEmpty.mask);
    } else {
        mw.visitLdcInsn(0);
    }
    mw.visitMethodInsn(INVOKEVIRTUAL, SerializeWriter, "writeNull", "(II)V");
    // seperator = ',';
    _seperator(mw, context);
    mw.visitJumpInsn(GOTO, _end_if);
    mw.visitLabel(_else);
    mw.visitLabel(_end_if);
}
Also used : JSONField(com.alibaba.fastjson.annotation.JSONField) JSONType(com.alibaba.fastjson.annotation.JSONType)

Example 13 with JSONType

use of com.alibaba.fastjson.annotation.JSONType in project uavstack by uavorg.

the class ASMSerializerFactory method createJavaBeanSerializer.

public ObjectSerializer createJavaBeanSerializer(Class<?> clazz, Map<String, String> aliasMap) throws Exception {
    if (clazz.isPrimitive()) {
        throw new JSONException("unsupportd class " + clazz.getName());
    }
    List<FieldInfo> getters = TypeUtils.computeGetters(clazz, aliasMap, false);
    for (FieldInfo getter : getters) {
        if (!ASMUtils.checkName(getter.getMember().getName())) {
            return null;
        }
    }
    String className = getGenClassName(clazz);
    int beanSerializeFeatures = TypeUtils.getSerializeFeatures(clazz);
    ClassWriter cw = new ClassWriter();
    cw.visit(V1_5, ACC_PUBLIC + ACC_SUPER, className, "com/alibaba/fastjson/serializer/ASMJavaBeanSerializer", new String[] { "com/alibaba/fastjson/serializer/ObjectSerializer" });
    for (FieldInfo fieldInfo : getters) {
        {
            FieldVisitor fw = cw.visitField(ACC_PUBLIC, fieldInfo.getName() + "_asm_fieldPrefix", "Ljava/lang/reflect/Type;");
            fw.visitEnd();
        }
        FieldVisitor fw = cw.visitField(ACC_PUBLIC, fieldInfo.getName() + "_asm_fieldType", "Ljava/lang/reflect/Type;");
        fw.visitEnd();
    }
    MethodVisitor mw = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
    mw.visitVarInsn(ALOAD, 0);
    mw.visitLdcInsn(com.alibaba.fastjson.asm.Type.getType(getDesc(clazz)));
    mw.visitMethodInsn(INVOKESPECIAL, "com/alibaba/fastjson/serializer/ASMJavaBeanSerializer", "<init>", "(Ljava/lang/Class;)V");
    for (FieldInfo fieldInfo : getters) {
        mw.visitVarInsn(ALOAD, 0);
        mw.visitLdcInsn(com.alibaba.fastjson.asm.Type.getType(getDesc(fieldInfo.getDeclaringClass())));
        if (fieldInfo.getMethod() != null) {
            mw.visitLdcInsn(fieldInfo.getMethod().getName());
            mw.visitMethodInsn(INVOKESTATIC, "com/alibaba/fastjson/util/ASMUtils", "getMethodType", "(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/reflect/Type;");
        } else {
            mw.visitLdcInsn(fieldInfo.getField().getName());
            mw.visitMethodInsn(INVOKESTATIC, "com/alibaba/fastjson/util/ASMUtils", "getFieldType", "(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/reflect/Type;");
        }
        mw.visitFieldInsn(PUTFIELD, className, fieldInfo.getName() + "_asm_fieldType", "Ljava/lang/reflect/Type;");
    }
    mw.visitInsn(RETURN);
    mw.visitMaxs(4, 4);
    mw.visitEnd();
    {
        Context context = new Context(className, beanSerializeFeatures);
        mw = cw.visitMethod(ACC_PUBLIC, "write", "(Lcom/alibaba/fastjson/serializer/JSONSerializer;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/reflect/Type;I)V", null, new String[] { "java/io/IOException" });
        // serializer
        mw.visitVarInsn(ALOAD, context.serializer());
        mw.visitMethodInsn(INVOKEVIRTUAL, "com/alibaba/fastjson/serializer/JSONSerializer", "getWriter", "()Lcom/alibaba/fastjson/serializer/SerializeWriter;");
        mw.visitVarInsn(ASTORE, context.var("out"));
        JSONType jsonType = clazz.getAnnotation(JSONType.class);
        if (jsonType == null || jsonType.alphabetic()) {
            Label _else = new Label();
            mw.visitVarInsn(ALOAD, context.var("out"));
            mw.visitFieldInsn(GETSTATIC, "com/alibaba/fastjson/serializer/SerializerFeature", "SortField", "Lcom/alibaba/fastjson/serializer/SerializerFeature;");
            mw.visitMethodInsn(INVOKEVIRTUAL, "com/alibaba/fastjson/serializer/SerializeWriter", "isEnabled", "(Lcom/alibaba/fastjson/serializer/SerializerFeature;)Z");
            mw.visitJumpInsn(IFEQ, _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, className, "write1", "(Lcom/alibaba/fastjson/serializer/JSONSerializer;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/reflect/Type;I)V");
            mw.visitInsn(RETURN);
            mw.visitLabel(_else);
        }
        // obj
        mw.visitVarInsn(ALOAD, context.obj());
        // serializer
        mw.visitTypeInsn(CHECKCAST, getType(clazz));
        // obj
        mw.visitVarInsn(ASTORE, context.var("entity"));
        generateWriteMethod(clazz, mw, getters, context);
        mw.visitInsn(RETURN);
        mw.visitMaxs(6, context.getVariantCount() + 1);
        mw.visitEnd();
    }
    List<FieldInfo> sortedGetters = TypeUtils.computeGetters(clazz, aliasMap, true);
    {
        // sortField support
        Context context = new Context(className, beanSerializeFeatures);
        mw = cw.visitMethod(ACC_PUBLIC, "write1", "(Lcom/alibaba/fastjson/serializer/JSONSerializer;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/reflect/Type;I)V", null, new String[] { "java/io/IOException" });
        // serializer
        mw.visitVarInsn(ALOAD, context.serializer());
        mw.visitMethodInsn(INVOKEVIRTUAL, "com/alibaba/fastjson/serializer/JSONSerializer", "getWriter", "()Lcom/alibaba/fastjson/serializer/SerializeWriter;");
        mw.visitVarInsn(ASTORE, context.var("out"));
        // obj
        mw.visitVarInsn(ALOAD, context.obj());
        // serializer
        mw.visitTypeInsn(CHECKCAST, getType(clazz));
        // obj
        mw.visitVarInsn(ASTORE, context.var("entity"));
        generateWriteMethod(clazz, mw, sortedGetters, context);
        mw.visitInsn(RETURN);
        mw.visitMaxs(6, context.getVariantCount() + 1);
        mw.visitEnd();
    }
    // writeAsArray
    {
        Context context = new Context(className, beanSerializeFeatures);
        mw = cw.visitMethod(ACC_PUBLIC, "writeAsArray", "(Lcom/alibaba/fastjson/serializer/JSONSerializer;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/reflect/Type;)V", null, new String[] { "java/io/IOException" });
        // serializer
        mw.visitVarInsn(ALOAD, context.serializer());
        mw.visitMethodInsn(INVOKEVIRTUAL, "com/alibaba/fastjson/serializer/JSONSerializer", "getWriter", "()Lcom/alibaba/fastjson/serializer/SerializeWriter;");
        mw.visitVarInsn(ASTORE, context.var("out"));
        // obj
        mw.visitVarInsn(ALOAD, context.obj());
        // serializer
        mw.visitTypeInsn(CHECKCAST, getType(clazz));
        // obj
        mw.visitVarInsn(ASTORE, context.var("entity"));
        generateWriteAsArray(clazz, mw, sortedGetters, context);
        mw.visitInsn(RETURN);
        mw.visitMaxs(6, context.getVariantCount() + 1);
        mw.visitEnd();
    }
    byte[] code = cw.toByteArray();
    if (JSON.DUMP_CLASS != null) {
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(JSON.DUMP_CLASS + File.separator + className + ".class");
            fos.write(code);
        } catch (Exception ex) {
        // System.err.println("FASTJSON dump class:"+className+"失败:"+ex.getMessage());
        } finally {
            if (fos != null) {
                fos.close();
            }
        }
    }
    Class<?> exampleClass = classLoader.defineClassPublic(className, code, 0, code.length);
    Object instance = exampleClass.newInstance();
    return (ObjectSerializer) instance;
}
Also used : Label(com.alibaba.fastjson.asm.Label) JSONException(com.alibaba.fastjson.JSONException) FieldVisitor(com.alibaba.fastjson.asm.FieldVisitor) ClassWriter(com.alibaba.fastjson.asm.ClassWriter) JSONException(com.alibaba.fastjson.JSONException) MethodVisitor(com.alibaba.fastjson.asm.MethodVisitor) FileOutputStream(java.io.FileOutputStream) JSONType(com.alibaba.fastjson.annotation.JSONType) FieldInfo(com.alibaba.fastjson.util.FieldInfo)

Example 14 with JSONType

use of com.alibaba.fastjson.annotation.JSONType in project fastjson by alibaba.

the class SerializeConfig method getObjectWriter.

public ObjectSerializer getObjectWriter(Class<?> clazz, boolean create) {
    ObjectSerializer writer = get(clazz);
    if (writer != null) {
        return writer;
    }
    try {
        final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        for (Object o : ServiceLoader.load(AutowiredObjectSerializer.class, classLoader)) {
            if (!(o instanceof AutowiredObjectSerializer)) {
                continue;
            }
            AutowiredObjectSerializer autowired = (AutowiredObjectSerializer) o;
            for (Type forType : autowired.getAutowiredFor()) {
                put(forType, autowired);
            }
        }
    } catch (ClassCastException ex) {
    // skip
    }
    writer = get(clazz);
    if (writer == null) {
        final ClassLoader classLoader = JSON.class.getClassLoader();
        if (classLoader != Thread.currentThread().getContextClassLoader()) {
            try {
                for (Object o : ServiceLoader.load(AutowiredObjectSerializer.class, classLoader)) {
                    if (!(o instanceof AutowiredObjectSerializer)) {
                        continue;
                    }
                    AutowiredObjectSerializer autowired = (AutowiredObjectSerializer) o;
                    for (Type forType : autowired.getAutowiredFor()) {
                        put(forType, autowired);
                    }
                }
            } catch (ClassCastException ex) {
            // skip
            }
            writer = get(clazz);
        }
    }
    for (Module module : modules) {
        writer = module.createSerializer(this, clazz);
        if (writer != null) {
            put(clazz, writer);
            return writer;
        }
    }
    if (writer == null) {
        String className = clazz.getName();
        Class<?> superClass;
        if (Map.class.isAssignableFrom(clazz)) {
            put(clazz, writer = MapSerializer.instance);
        } else if (List.class.isAssignableFrom(clazz)) {
            put(clazz, writer = ListSerializer.instance);
        } else if (Collection.class.isAssignableFrom(clazz)) {
            put(clazz, writer = CollectionCodec.instance);
        } else if (Date.class.isAssignableFrom(clazz)) {
            put(clazz, writer = DateCodec.instance);
        } else if (JSONAware.class.isAssignableFrom(clazz)) {
            put(clazz, writer = JSONAwareSerializer.instance);
        } else if (JSONSerializable.class.isAssignableFrom(clazz)) {
            put(clazz, writer = JSONSerializableSerializer.instance);
        } else if (JSONStreamAware.class.isAssignableFrom(clazz)) {
            put(clazz, writer = MiscCodec.instance);
        } else if (clazz.isEnum()) {
            Class mixedInType = (Class) JSON.getMixInAnnotations(clazz);
            JSONType jsonType;
            if (mixedInType != null) {
                jsonType = TypeUtils.getAnnotation(mixedInType, JSONType.class);
            } else {
                jsonType = TypeUtils.getAnnotation(clazz, JSONType.class);
            }
            if (jsonType != null && jsonType.serializeEnumAsJavaBean()) {
                put(clazz, writer = createJavaBeanSerializer(clazz));
            } else {
                Member member = null;
                if (mixedInType != null) {
                    Member mixedInMember = getEnumValueField(mixedInType);
                    if (mixedInMember != null) {
                        try {
                            if (mixedInMember instanceof Method) {
                                Method mixedInMethod = (Method) mixedInMember;
                                member = clazz.getMethod(mixedInMethod.getName(), mixedInMethod.getParameterTypes());
                            }
                        } catch (Exception e) {
                        // skip
                        }
                    }
                } else {
                    member = getEnumValueField(clazz);
                }
                if (member != null) {
                    put(clazz, writer = new EnumSerializer(member));
                } else {
                    put(clazz, writer = getEnumSerializer());
                }
            }
        } else if ((superClass = clazz.getSuperclass()) != null && superClass.isEnum()) {
            JSONType jsonType = TypeUtils.getAnnotation(superClass, JSONType.class);
            if (jsonType != null && jsonType.serializeEnumAsJavaBean()) {
                put(clazz, writer = createJavaBeanSerializer(clazz));
            } else {
                put(clazz, writer = getEnumSerializer());
            }
        } else if (clazz.isArray()) {
            Class<?> componentType = clazz.getComponentType();
            ObjectSerializer compObjectSerializer = getObjectWriter(componentType);
            put(clazz, writer = new ArraySerializer(componentType, compObjectSerializer));
        } else if (Throwable.class.isAssignableFrom(clazz)) {
            SerializeBeanInfo beanInfo = TypeUtils.buildBeanInfo(clazz, null, propertyNamingStrategy);
            beanInfo.features |= SerializerFeature.WriteClassName.mask;
            put(clazz, writer = new JavaBeanSerializer(beanInfo));
        } else if (TimeZone.class.isAssignableFrom(clazz) || Map.Entry.class.isAssignableFrom(clazz)) {
            put(clazz, writer = MiscCodec.instance);
        } else if (Appendable.class.isAssignableFrom(clazz)) {
            put(clazz, writer = AppendableSerializer.instance);
        } else if (Charset.class.isAssignableFrom(clazz)) {
            put(clazz, writer = ToStringSerializer.instance);
        } else if (Enumeration.class.isAssignableFrom(clazz)) {
            put(clazz, writer = EnumerationSerializer.instance);
        } else if (// 
        Calendar.class.isAssignableFrom(clazz) || XMLGregorianCalendar.class.isAssignableFrom(clazz)) {
            put(clazz, writer = CalendarCodec.instance);
        } else if (TypeUtils.isClob(clazz)) {
            put(clazz, writer = ClobSerializer.instance);
        } else if (TypeUtils.isPath(clazz)) {
            put(clazz, writer = ToStringSerializer.instance);
        } else if (Iterator.class.isAssignableFrom(clazz)) {
            put(clazz, writer = MiscCodec.instance);
        } else if (org.w3c.dom.Node.class.isAssignableFrom(clazz)) {
            put(clazz, writer = MiscCodec.instance);
        } else {
            if (// 
            className.startsWith("java.awt.") && // 
            AwtCodec.support(clazz)) {
                // awt
                if (!awtError) {
                    try {
                        String[] names = new String[] { "java.awt.Color", "java.awt.Font", "java.awt.Point", "java.awt.Rectangle" };
                        for (String name : names) {
                            if (name.equals(className)) {
                                put(Class.forName(name), writer = AwtCodec.instance);
                                return writer;
                            }
                        }
                    } catch (Throwable e) {
                        awtError = true;
                    // skip
                    }
                }
            }
            // jdk8
            if (// 
            (!jdk8Error) && (// 
            className.startsWith("java.time.") || // 
            className.startsWith("java.util.Optional") || className.equals("java.util.concurrent.atomic.LongAdder") || className.equals("java.util.concurrent.atomic.DoubleAdder"))) {
                try {
                    {
                        String[] names = new String[] { "java.time.LocalDateTime", "java.time.LocalDate", "java.time.LocalTime", "java.time.ZonedDateTime", "java.time.OffsetDateTime", "java.time.OffsetTime", "java.time.ZoneOffset", "java.time.ZoneRegion", "java.time.Period", "java.time.Duration", "java.time.Instant" };
                        for (String name : names) {
                            if (name.equals(className)) {
                                put(Class.forName(name), writer = Jdk8DateCodec.instance);
                                return writer;
                            }
                        }
                    }
                    {
                        String[] names = new String[] { "java.util.Optional", "java.util.OptionalDouble", "java.util.OptionalInt", "java.util.OptionalLong" };
                        for (String name : names) {
                            if (name.equals(className)) {
                                put(Class.forName(name), writer = OptionalCodec.instance);
                                return writer;
                            }
                        }
                    }
                    {
                        String[] names = new String[] { "java.util.concurrent.atomic.LongAdder", "java.util.concurrent.atomic.DoubleAdder" };
                        for (String name : names) {
                            if (name.equals(className)) {
                                put(Class.forName(name), writer = AdderSerializer.instance);
                                return writer;
                            }
                        }
                    }
                } catch (Throwable e) {
                    // skip
                    jdk8Error = true;
                }
            }
            if (// 
            (!oracleJdbcError) && className.startsWith("oracle.sql.")) {
                try {
                    String[] names = new String[] { "oracle.sql.DATE", "oracle.sql.TIMESTAMP" };
                    for (String name : names) {
                        if (name.equals(className)) {
                            put(Class.forName(name), writer = DateCodec.instance);
                            return writer;
                        }
                    }
                } catch (Throwable e) {
                    // skip
                    oracleJdbcError = true;
                }
            }
            if (// 
            (!springfoxError) && className.equals("springfox.documentation.spring.web.json.Json")) {
                try {
                    put(// 
                    Class.forName("springfox.documentation.spring.web.json.Json"), writer = SwaggerJsonSerializer.instance);
                    return writer;
                } catch (ClassNotFoundException e) {
                    // skip
                    springfoxError = true;
                }
            }
            if (// 
            (!guavaError) && className.startsWith("com.google.common.collect.")) {
                try {
                    String[] names = new String[] { "com.google.common.collect.HashMultimap", "com.google.common.collect.LinkedListMultimap", "com.google.common.collect.LinkedHashMultimap", "com.google.common.collect.ArrayListMultimap", "com.google.common.collect.TreeMultimap" };
                    for (String name : names) {
                        if (name.equals(className)) {
                            put(Class.forName(name), writer = GuavaCodec.instance);
                            return writer;
                        }
                    }
                } catch (ClassNotFoundException e) {
                    // skip
                    guavaError = true;
                }
            }
            if (className.equals("net.sf.json.JSONNull")) {
                put(clazz, writer = MiscCodec.instance);
                return writer;
            }
            if (className.equals("org.json.JSONObject")) {
                put(clazz, writer = JSONObjectCodec.instance);
                return writer;
            }
            if ((!jodaError) && className.startsWith("org.joda.")) {
                try {
                    String[] names = new String[] { "org.joda.time.LocalDate", "org.joda.time.LocalDateTime", "org.joda.time.LocalTime", "org.joda.time.Instant", "org.joda.time.DateTime", "org.joda.time.Period", "org.joda.time.Duration", "org.joda.time.DateTimeZone", "org.joda.time.UTCDateTimeZone", "org.joda.time.tz.CachedDateTimeZone", "org.joda.time.tz.FixedDateTimeZone" };
                    for (String name : names) {
                        if (name.equals(className)) {
                            put(Class.forName(name), writer = JodaCodec.instance);
                            return writer;
                        }
                    }
                } catch (ClassNotFoundException e) {
                    // skip
                    jodaError = true;
                }
            }
            if ("java.nio.HeapByteBuffer".equals(className)) {
                put(clazz, writer = ByteBufferCodec.instance);
                return writer;
            }
            if ("org.javamoney.moneta.Money".equals(className)) {
                put(clazz, writer = MonetaCodec.instance);
                return writer;
            }
            if ("com.google.protobuf.Descriptors$FieldDescriptor".equals(className)) {
                put(clazz, writer = ToStringSerializer.instance);
                return writer;
            }
            Class[] interfaces = clazz.getInterfaces();
            if (interfaces.length == 1 && interfaces[0].isAnnotation()) {
                put(clazz, AnnotationSerializer.instance);
                return AnnotationSerializer.instance;
            }
            if (TypeUtils.isProxy(clazz)) {
                Class<?> superClazz = clazz.getSuperclass();
                ObjectSerializer superWriter = getObjectWriter(superClazz);
                put(clazz, superWriter);
                return superWriter;
            }
            if (Proxy.isProxyClass(clazz)) {
                Class handlerClass = null;
                if (interfaces.length == 2) {
                    handlerClass = interfaces[1];
                } else {
                    for (Class proxiedInterface : interfaces) {
                        if (proxiedInterface.getName().startsWith("org.springframework.aop.")) {
                            continue;
                        }
                        if (handlerClass != null) {
                            // multi-matched
                            handlerClass = null;
                            break;
                        }
                        handlerClass = proxiedInterface;
                    }
                }
                if (handlerClass != null) {
                    ObjectSerializer superWriter = getObjectWriter(handlerClass);
                    put(clazz, superWriter);
                    return superWriter;
                }
            }
            if (create) {
                writer = createJavaBeanSerializer(clazz);
                put(clazz, writer);
            }
        }
        if (writer == null) {
            writer = get(clazz);
        }
    }
    return writer;
}
Also used : Charset(java.nio.charset.Charset) JSONType(com.alibaba.fastjson.annotation.JSONType) Module(com.alibaba.fastjson.spi.Module) JSONType(com.alibaba.fastjson.annotation.JSONType) IdentityHashMap(com.alibaba.fastjson.util.IdentityHashMap)

Example 15 with JSONType

use of com.alibaba.fastjson.annotation.JSONType 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 = TypeUtils.getAnnotation(clazz, JSONType.class);
    FieldInfo[] unsortedGetters = beanInfo.fields;
    for (FieldInfo fieldInfo : unsortedGetters) {
        if (// 
        fieldInfo.field == null && // 
        fieldInfo.method != null && fieldInfo.method.getDeclaringClass().isInterface()) {
            return new JavaBeanSerializer(beanInfo);
        }
    }
    FieldInfo[] getters = beanInfo.sortedFields;
    boolean nativeSorted = beanInfo.sortedFields == beanInfo.fields;
    if (getters.length > 256) {
        return new JavaBeanSerializer(beanInfo);
    }
    for (FieldInfo getter : getters) {
        if (!ASMUtils.checkName(getter.getMember().getName())) {
            return new JavaBeanSerializer(beanInfo);
        }
    }
    String className = "ASMSerializer_" + seed.incrementAndGet() + "_" + clazz.getSimpleName();
    String classNameType;
    String classNameFull;
    Package pkg = ASMSerializerFactory.class.getPackage();
    if (pkg != null) {
        String packageName = pkg.getName();
        classNameType = packageName.replace('.', '/') + "/" + className;
        classNameFull = packageName + "." + className;
    } else {
        classNameType = className;
        classNameFull = 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<?> serializerClass = classLoader.defineClassPublic(classNameFull, code, 0, code.length);
    Constructor<?> constructor = serializerClass.getConstructor(SerializeBeanInfo.class);
    Object instance = constructor.newInstance(beanInfo);
    return (JavaBeanSerializer) instance;
}
Also used : JSONException(com.alibaba.fastjson.JSONException) ASMUtils(com.alibaba.fastjson.util.ASMUtils) JSONType(com.alibaba.fastjson.annotation.JSONType) FieldInfo(com.alibaba.fastjson.util.FieldInfo)

Aggregations

JSONType (com.alibaba.fastjson.annotation.JSONType)25 JSONField (com.alibaba.fastjson.annotation.JSONField)14 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)8 JSONException (com.alibaba.fastjson.JSONException)7 Field (java.lang.reflect.Field)5 PropertyNamingStrategy (com.alibaba.fastjson.PropertyNamingStrategy)4 IdentityHashMap (com.alibaba.fastjson.util.IdentityHashMap)4 AccessControlException (java.security.AccessControlException)4 JSONPOJOBuilder (com.alibaba.fastjson.annotation.JSONPOJOBuilder)3 SerializeBeanInfo (com.alibaba.fastjson.serializer.SerializeBeanInfo)3 FieldInfo (com.alibaba.fastjson.util.FieldInfo)3 Annotation (java.lang.annotation.Annotation)3 Type (java.lang.reflect.Type)3 LinkedHashMap (java.util.LinkedHashMap)3 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)3 AtomicLong (java.util.concurrent.atomic.AtomicLong)3 JSONObject (com.alibaba.fastjson.JSONObject)2 Module (com.alibaba.fastjson.spi.Module)2 ASMUtils (com.alibaba.fastjson.util.ASMUtils)2 Method (java.lang.reflect.Method)2