package com.alibaba.fastjson.serializer; import static com.alibaba.fastjson.util.ASMUtils.getDesc; import static com.alibaba.fastjson.util.ASMUtils.getType; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.math.BigDecimal; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicLong; import com.alibaba.fastjson.JSONException; import com.alibaba.fastjson.annotation.JSONField; import com.alibaba.fastjson.annotation.JSONType; import com.alibaba.fastjson.util.ASMClassLoader; import com.alibaba.fastjson.util.ASMUtils; import com.alibaba.fastjson.util.FieldInfo; import com.alibaba.fastjson.util.TypeUtils; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.FieldVisitor; import org.objectweb.asm.Label; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; public class ASMSerializerFactory implements Opcodes { private final ASMClassLoader classLoader = new ASMClassLoader(); public ObjectSerializer createJavaBeanSerializer(Class<?> clazz) throws Exception { return createJavaBeanSerializer(clazz, (Map<String, String>) null); } private final AtomicLong seed = new AtomicLong(); public String getGenClassName(Class<?> clazz) { return "Serializer_" + seed.incrementAndGet(); } public boolean isExternalClass(Class<?> clazz) { return classLoader.isExternalClass(clazz); } static class Context { private final String className; public Context(String className) { this.className = className; } private int variantIndex = 8; private Map<String, Integer> variants = new HashMap<String, Integer>(); public int serializer() { return 1; } public String getClassName() { return className; } public int obj() { return 2; } public int paramFieldName() { return 3; } public int paramFieldType() { return 4; } public int fieldName() { return 5; } public int original() { return 6; } public int processValue() { return 7; } public int getVariantCount() { return variantIndex; } public int var(String name) { Integer i = variants.get(name); if (i == null) { variants.put(name, variantIndex++); } i = variants.get(name); return i.intValue(); } public int var(String name, int increment) { Integer i = variants.get(name); if (i == null) { variants.put(name, variantIndex); variantIndex += increment; } i = variants.get(name); return i.intValue(); } } 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); String className = getGenClassName(clazz); ClassWriter cw = new ClassWriter(0); cw.visit(V1_5, ACC_PUBLIC + ACC_SUPER, className, null, "java/lang/Object", new String[]{"com/alibaba/fastjson/serializer/ObjectSerializer"}); { FieldVisitor fw = cw.visitField(ACC_PRIVATE, "nature", getDesc(JavaBeanSerializer.class), null, null); fw.visitEnd(); } for (FieldInfo fieldInfo : getters) { FieldVisitor fw = cw.visitField(ACC_PUBLIC, fieldInfo.getName() + "_asm_fieldType", "Ljava/lang/reflect/Type;", null, null); fw.visitEnd(); } MethodVisitor mw = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null); mw.visitVarInsn(ALOAD, 0); mw.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V"); // mw.visitFieldInsn(PUTFIELD, context.getClassName(), fieldInfo.getName() + "_asm_prefix__", "[C"); for (FieldInfo fieldInfo : getters) { mw.visitVarInsn(ALOAD, 0); mw.visitLdcInsn(org.objectweb.asm.Type.getType(fieldInfo.getDeclaringClass())); if (fieldInfo.getMethod() != null) { mw.visitLdcInsn(fieldInfo.getMethod().getName()); mw.visitMethodInsn(INVOKESTATIC, getType(ASMUtils.class), "getMethodType", "(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/reflect/Type;"); } else { mw.visitLdcInsn(fieldInfo.getField().getName()); mw.visitMethodInsn(INVOKESTATIC, getType(ASMUtils.class), "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); mw = cw.visitMethod(ACC_PUBLIC, "write", "(Lcom/alibaba/fastjson/serializer/JSONSerializer;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/reflect/Type;)V", null, new String[]{"java/io/IOException"}); mw.visitVarInsn(ALOAD, context.serializer()); // serializer mw.visitMethodInsn(INVOKEVIRTUAL, getType(JSONSerializer.class), "getWriter", "()" + getDesc(SerializeWriter.class)); 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, getType(SerializerFeature.class), "SortField", "L" + getType(SerializerFeature.class) + ";"); mw.visitMethodInsn(INVOKEVIRTUAL, getType(SerializeWriter.class), "isEnabled", "(" + "L" + getType(SerializerFeature.class) + ";" + ")Z"); mw.visitJumpInsn(IFEQ, _else); mw.visitVarInsn(ALOAD, 0); mw.visitVarInsn(ALOAD, 1); mw.visitVarInsn(ALOAD, 2); mw.visitVarInsn(ALOAD, 3); mw.visitVarInsn(ALOAD, context.paramFieldType()); mw.visitMethodInsn(INVOKEVIRTUAL, className, "write1", "(Lcom/alibaba/fastjson/serializer/JSONSerializer;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/reflect/Type;)V"); mw.visitInsn(RETURN); mw.visitLabel(_else); } mw.visitVarInsn(ALOAD, context.obj()); // obj mw.visitTypeInsn(CHECKCAST, getType(clazz)); // serializer mw.visitVarInsn(ASTORE, context.var("entity")); // obj generateWriteMethod(clazz, mw, getters, context); mw.visitInsn(RETURN); mw.visitMaxs(5, context.getVariantCount() + 1); mw.visitEnd(); } List<FieldInfo> sortedGetters = TypeUtils.computeGetters(clazz, aliasMap, true); { // sortField support Context context = new Context(className); mw = cw.visitMethod(ACC_PUBLIC, "write1", "(Lcom/alibaba/fastjson/serializer/JSONSerializer;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/reflect/Type;)V", null, new String[]{"java/io/IOException"}); mw.visitVarInsn(ALOAD, context.serializer()); // serializer mw.visitMethodInsn(INVOKEVIRTUAL, getType(JSONSerializer.class), "getWriter", "()" + getDesc(SerializeWriter.class)); mw.visitVarInsn(ASTORE, context.var("out")); mw.visitVarInsn(ALOAD, context.obj()); // obj mw.visitTypeInsn(CHECKCAST, getType(clazz)); // serializer mw.visitVarInsn(ASTORE, context.var("entity")); // obj generateWriteMethod(clazz, mw, sortedGetters, context); mw.visitInsn(RETURN); mw.visitMaxs(5, context.getVariantCount() + 1); mw.visitEnd(); } byte[] code = cw.toByteArray(); // // org.apache.commons.io.IOUtils.write(code, new java.io.FileOutputStream( // "/usr/alibaba/workspace-3.7/fastjson-asm/target/classes/" // + className + ".class")); Class<?> exampleClass = classLoader.defineClassPublic(className, code, 0, code.length); Object instance = exampleClass.newInstance(); return (ObjectSerializer) instance; } private void generateWriteMethod(Class<?> clazz, MethodVisitor mw, List<FieldInfo> getters, Context context) throws Exception { Label end = new Label(); int size = getters.size(); { // 格式化输出不走asm 优化 Label endFormat_ = new Label(); Label notNull_ = new Label(); mw.visitVarInsn(ALOAD, context.var("out")); mw.visitFieldInsn(GETSTATIC, getType(SerializerFeature.class), "PrettyFormat", "L" + getType(SerializerFeature.class) + ";"); mw.visitMethodInsn(INVOKEVIRTUAL, getType(SerializeWriter.class), "isEnabled", "(" + "L" + getType(SerializerFeature.class) + ";" + ")Z"); mw.visitJumpInsn(IFEQ, endFormat_); mw.visitVarInsn(ALOAD, 0); mw.visitFieldInsn(GETFIELD, context.getClassName(), "nature", getDesc(JavaBeanSerializer.class)); mw.visitJumpInsn(IFNONNULL, notNull_); initNature(clazz, mw, context); // ///// mw.visitLabel(notNull_); mw.visitVarInsn(ALOAD, 0); mw.visitFieldInsn(GETFIELD, context.getClassName(), "nature", getDesc(JavaBeanSerializer.class)); mw.visitVarInsn(ALOAD, 1); mw.visitVarInsn(ALOAD, 2); mw.visitVarInsn(ALOAD, 3); mw.visitVarInsn(ALOAD, 4); mw.visitMethodInsn(INVOKEVIRTUAL, getType(JavaBeanSerializer.class), "write", "(Lcom/alibaba/fastjson/serializer/JSONSerializer;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/reflect/Type;)V"); mw.visitInsn(RETURN); mw.visitLabel(endFormat_); } { // if (serializer.containsReference(object)) { Label endRef_ = new Label(); Label notNull_ = new Label(); mw.visitVarInsn(ALOAD, context.serializer()); mw.visitVarInsn(ALOAD, context.obj()); mw.visitMethodInsn(INVOKEVIRTUAL, getType(JSONSerializer.class), "containsReference", "(Ljava/lang/Object;)Z"); mw.visitJumpInsn(IFEQ, endRef_); mw.visitVarInsn(ALOAD, 0); mw.visitFieldInsn(GETFIELD, context.getClassName(), "nature", getDesc(JavaBeanSerializer.class)); mw.visitJumpInsn(IFNONNULL, notNull_); initNature(clazz, mw, context); // ///// mw.visitLabel(notNull_); mw.visitVarInsn(ALOAD, 0); mw.visitFieldInsn(GETFIELD, context.getClassName(), "nature", getDesc(JavaBeanSerializer.class)); mw.visitVarInsn(ALOAD, 1); mw.visitVarInsn(ALOAD, 2); mw.visitMethodInsn(INVOKEVIRTUAL, getType(JavaBeanSerializer.class), "writeReference", "(Lcom/alibaba/fastjson/serializer/JSONSerializer;Ljava/lang/Object;)V"); mw.visitInsn(RETURN); mw.visitLabel(endRef_); } { mw.visitVarInsn(ALOAD, context.serializer()); mw.visitMethodInsn(INVOKEVIRTUAL, getType(JSONSerializer.class), "getContext", "()Lcom/alibaba/fastjson/serializer/SerialContext;"); mw.visitVarInsn(ASTORE, context.var("parent")); mw.visitVarInsn(ALOAD, context.serializer()); mw.visitVarInsn(ALOAD, context.var("parent")); mw.visitVarInsn(ALOAD, context.obj()); mw.visitVarInsn(ALOAD, context.paramFieldName()); mw.visitMethodInsn(INVOKEVIRTUAL, getType(JSONSerializer.class), "setContext", "(Lcom/alibaba/fastjson/serializer/SerialContext;Ljava/lang/Object;Ljava/lang/Object;)V"); } // SEPERATO { Label end_ = new Label(); Label else_ = new Label(); Label writeClass_ = new Label(); // mw.visitVarInsn(ALOAD, context.var("out")); // mw.visitFieldInsn(GETSTATIC, getType(SerializerFeature.class), "WriteClassName", // "L" + getType(SerializerFeature.class) + ";"); // mw.visitMethodInsn(INVOKEVIRTUAL, getType(SerializeWriter.class), "isEnabled", // "(" + "L" + getType(SerializerFeature.class) + ";" + ")Z"); // mw.visitJumpInsn(IFEQ, else_); mw.visitVarInsn(ALOAD, context.serializer()); mw.visitVarInsn(ALOAD, context.paramFieldType()); mw.visitVarInsn(ALOAD, context.obj()); mw.visitMethodInsn(INVOKEVIRTUAL, getType(JSONSerializer.class), "isWriteClassName", "(Ljava/lang/reflect/Type;Ljava/lang/Object;)Z"); mw.visitJumpInsn(IFEQ, else_); // mw.visitVarInsn(ALOAD, context.paramFieldType()); // mw.visitJumpInsn(IFNULL, writeClass_); // IFNULL mw.visitVarInsn(ALOAD, context.paramFieldType()); mw.visitVarInsn(ALOAD, context.obj()); mw.visitMethodInsn(INVOKEVIRTUAL, getType(Object.class), "getClass", "()Ljava/lang/Class;"); mw.visitJumpInsn(IF_ACMPEQ, else_); mw.visitLabel(writeClass_); mw.visitVarInsn(ALOAD, context.var("out")); // Kevin Zou // 序列化时检查JSONType中是否有定义shortType如果有则采用shortType作为@type的值反之采用class.getName() String clazzName = clazz.getName(); JSONType jsonType = clazz.getAnnotation(JSONType.class); if (jsonType != null && !"".equals(jsonType.shortType())) { clazzName = jsonType.shortType(); } mw.visitLdcInsn("{\"@type\":\"" + clazzName + "\""); mw.visitMethodInsn(INVOKEVIRTUAL, getType(SerializeWriter.class), "write", "(Ljava/lang/String;)V"); mw.visitVarInsn(BIPUSH, ','); mw.visitJumpInsn(GOTO, end_); mw.visitLabel(else_); mw.visitVarInsn(BIPUSH, '{'); mw.visitLabel(end_); } mw.visitVarInsn(ISTORE, context.var("seperator")); for (int i = 0; i < size; ++i) { FieldInfo property = getters.get(i); Class<?> propertyClass = property.getFieldClass(); mw.visitLdcInsn(property.getName()); mw.visitVarInsn(ASTORE, context.fieldName()); if (propertyClass == byte.class) { _byte(clazz, mw, property, context); } else if (propertyClass == short.class) { _short(clazz, mw, property, context); } else if (propertyClass == int.class) { _int(clazz, mw, property, context); } else if (propertyClass == long.class) { _long(clazz, mw, property, context); } else if (propertyClass == float.class) { _float(clazz, mw, property, context); } else if (propertyClass == double.class) { _double(clazz, mw, property, context); } else if (propertyClass == boolean.class) { _boolean(clazz, mw, property, context); } else if (propertyClass == char.class) { _char(clazz, mw, property, context); } else if (propertyClass == String.class) { _string(clazz, mw, property, context); } else if (propertyClass == BigDecimal.class) { _decimal(clazz, mw, property, context); } else if (List.class.isAssignableFrom(propertyClass)) { _list(clazz, mw, property, context); // _object(clazz, mw, property, context); } else if (propertyClass.isEnum()) { _enum(clazz, mw, property, context); } else { _object(clazz, mw, property, context); } } Label _if = new Label(); Label _else = new Label(); Label _end_if = new Label(); mw.visitLabel(_if); // if (seperator == '{') mw.visitVarInsn(ILOAD, context.var("seperator")); mw.visitIntInsn(BIPUSH, '{'); mw.visitJumpInsn(IF_ICMPNE, _else); mw.visitVarInsn(ALOAD, context.var("out")); mw.visitLdcInsn("{}"); mw.visitMethodInsn(INVOKEVIRTUAL, getType(SerializeWriter.class), "write", "(Ljava/lang/String;)V"); mw.visitJumpInsn(GOTO, _end_if); mw.visitLabel(_else); mw.visitVarInsn(ALOAD, context.var("out")); mw.visitVarInsn(BIPUSH, '}'); mw.visitMethodInsn(INVOKEVIRTUAL, getType(SerializeWriter.class), "write", "(C)V"); mw.visitLabel(_end_if); mw.visitLabel(end); mw.visitVarInsn(ALOAD, context.serializer()); mw.visitVarInsn(ALOAD, context.var("parent")); mw.visitMethodInsn(INVOKEVIRTUAL, getType(JSONSerializer.class), "setContext", "(Lcom/alibaba/fastjson/serializer/SerialContext;)V"); } private void initNature(Class<?> clazz, MethodVisitor mw, Context context) { mw.visitVarInsn(ALOAD, 0); mw.visitTypeInsn(NEW, getType(JavaBeanSerializer.class)); mw.visitInsn(DUP); mw.visitLdcInsn(org.objectweb.asm.Type.getType(clazz)); mw.visitMethodInsn(INVOKESPECIAL, getType(JavaBeanSerializer.class), "<init>", "(" + getDesc(Class.class) + ")V"); mw.visitFieldInsn(PUTFIELD, context.getClassName(), "nature", getDesc(JavaBeanSerializer.class)); } private void _object(Class<?> clazz, MethodVisitor mw, FieldInfo property, Context context) { Label _end = new Label(); _nameApply(mw, property, context, _end); _get(mw, context, property); mw.visitVarInsn(ASTORE, context.var("object")); _filters(mw, property, context, _end); _writeObject(mw, property, context, _end); mw.visitLabel(_end); } private void _enum(Class<?> clazz, MethodVisitor mw, FieldInfo property, Context context) { boolean writeEnumUsingToString = false; JSONField annotation = property.getAnnotation(JSONField.class); if (annotation != null) { for (SerializerFeature feature : annotation.serialzeFeatures()) { if (feature == SerializerFeature.WriteEnumUsingToString) { writeEnumUsingToString = true; } } } Label _not_null = new Label(); Label _end_if = new Label(); Label _end = new Label(); _nameApply(mw, property, context, _end); _get(mw, context, property); mw.visitTypeInsn(CHECKCAST, getType(Enum.class)); // cast mw.visitVarInsn(ASTORE, context.var("enum")); _filters(mw, property, context, _end); mw.visitVarInsn(ALOAD, context.var("enum")); mw.visitJumpInsn(IFNONNULL, _not_null); _if_write_null(mw, property, context); mw.visitJumpInsn(GOTO, _end_if); mw.visitLabel(_not_null); mw.visitVarInsn(ALOAD, context.var("out")); mw.visitVarInsn(ILOAD, context.var("seperator")); mw.visitVarInsn(ALOAD, context.fieldName()); mw.visitVarInsn(ALOAD, context.var("enum")); if (writeEnumUsingToString) { mw.visitMethodInsn(INVOKEVIRTUAL, getType(Object.class), "toString", "()Ljava/lang/String;"); mw.visitMethodInsn(INVOKEVIRTUAL, getType(SerializeWriter.class), "writeFieldValue", "(CLjava/lang/String;Ljava/lang/String;)V"); } else { mw.visitMethodInsn(INVOKEVIRTUAL, getType(SerializeWriter.class), "writeFieldValue", "(CLjava/lang/String;L" + getType(Enum.class) + ";)V"); } _seperator(mw, context); mw.visitLabel(_end_if); mw.visitLabel(_end); } private void _long(Class<?> clazz, MethodVisitor mw, FieldInfo property, Context context) { Label _end = new Label(); _nameApply(mw, property, context, _end); _get(mw, context, property); mw.visitVarInsn(LSTORE, context.var("long", 2)); _filters(mw, property, context, _end); mw.visitVarInsn(ALOAD, context.var("out")); mw.visitVarInsn(ILOAD, context.var("seperator")); mw.visitVarInsn(ALOAD, context.fieldName()); mw.visitVarInsn(LLOAD, context.var("long", 2)); mw.visitMethodInsn(INVOKEVIRTUAL, getType(SerializeWriter.class), "writeFieldValue", "(CLjava/lang/String;J)V"); _seperator(mw, context); mw.visitLabel(_end); } private void _float(Class<?> clazz, MethodVisitor mw, FieldInfo property, Context context) { Label _end = new Label(); _nameApply(mw, property, context, _end); _get(mw, context, property); mw.visitVarInsn(FSTORE, context.var("float")); _filters(mw, property, context, _end); mw.visitVarInsn(ALOAD, context.var("out")); mw.visitVarInsn(ILOAD, context.var("seperator")); mw.visitVarInsn(ALOAD, context.fieldName()); mw.visitVarInsn(FLOAD, context.var("float")); mw.visitMethodInsn(INVOKEVIRTUAL, getType(SerializeWriter.class), "writeFieldValue", "(CLjava/lang/String;F)V"); _seperator(mw, context); mw.visitLabel(_end); } private void _double(Class<?> clazz, MethodVisitor mw, FieldInfo property, Context context) { Label _end = new Label(); _nameApply(mw, property, context, _end); _get(mw, context, property); mw.visitVarInsn(DSTORE, context.var("double", 2)); _filters(mw, property, context, _end); mw.visitVarInsn(ALOAD, context.var("out")); mw.visitVarInsn(ILOAD, context.var("seperator")); mw.visitVarInsn(ALOAD, context.fieldName()); mw.visitVarInsn(DLOAD, context.var("double", 2)); mw.visitMethodInsn(INVOKEVIRTUAL, getType(SerializeWriter.class), "writeFieldValue", "(CLjava/lang/String;D)V"); _seperator(mw, context); mw.visitLabel(_end); } private void _char(Class<?> clazz, MethodVisitor mw, FieldInfo property, Context context) { Label _end = new Label(); _nameApply(mw, property, context, _end); _get(mw, context, property); mw.visitVarInsn(ISTORE, context.var("char")); _filters(mw, property, context, _end); mw.visitVarInsn(ALOAD, context.var("out")); mw.visitVarInsn(ILOAD, context.var("seperator")); mw.visitVarInsn(ALOAD, context.fieldName()); mw.visitVarInsn(ILOAD, context.var("char")); mw.visitMethodInsn(INVOKEVIRTUAL, getType(SerializeWriter.class), "writeFieldValue", "(CLjava/lang/String;C)V"); _seperator(mw, context); mw.visitLabel(_end); } private void _boolean(Class<?> clazz, MethodVisitor mw, FieldInfo property, Context context) { Label _end = new Label(); _nameApply(mw, property, context, _end); _get(mw, context, property); mw.visitVarInsn(ISTORE, context.var("boolean")); _filters(mw, property, context, _end); mw.visitVarInsn(ALOAD, context.var("out")); mw.visitVarInsn(ILOAD, context.var("seperator")); mw.visitVarInsn(ALOAD, context.fieldName()); mw.visitVarInsn(ILOAD, context.var("boolean")); mw.visitMethodInsn(INVOKEVIRTUAL, getType(SerializeWriter.class), "writeFieldValue", "(CLjava/lang/String;Z)V"); _seperator(mw, context); mw.visitLabel(_end); } private void _get(MethodVisitor mw, Context context, FieldInfo property) { Method method = property.getMethod(); if (method != null) { mw.visitVarInsn(ALOAD, context.var("entity")); mw.visitMethodInsn(INVOKEVIRTUAL, getType(method.getDeclaringClass()), method.getName(), getDesc(method)); } else { mw.visitVarInsn(ALOAD, context.var("entity")); mw.visitFieldInsn(GETFIELD, getType(property.getDeclaringClass()), property.getName(), getDesc(property.getFieldClass())); } } private void _byte(Class<?> clazz, MethodVisitor mw, FieldInfo property, Context context) { Label _end = new Label(); _nameApply(mw, property, context, _end); _get(mw, context, property); mw.visitVarInsn(ISTORE, context.var("byte")); _filters(mw, property, context, _end); mw.visitVarInsn(ALOAD, context.var("out")); mw.visitVarInsn(ILOAD, context.var("seperator")); mw.visitVarInsn(ALOAD, context.fieldName()); mw.visitVarInsn(ILOAD, context.var("byte")); mw.visitMethodInsn(INVOKEVIRTUAL, getType(SerializeWriter.class), "writeFieldValue", "(CLjava/lang/String;I)V"); _seperator(mw, context); mw.visitLabel(_end); } private void _short(Class<?> clazz, MethodVisitor mw, FieldInfo property, Context context) { Label _end = new Label(); _nameApply(mw, property, context, _end); _get(mw, context, property); mw.visitVarInsn(ISTORE, context.var("short")); _filters(mw, property, context, _end); mw.visitVarInsn(ALOAD, context.var("out")); mw.visitVarInsn(ILOAD, context.var("seperator")); mw.visitVarInsn(ALOAD, context.fieldName()); mw.visitVarInsn(ILOAD, context.var("short")); mw.visitMethodInsn(INVOKEVIRTUAL, getType(SerializeWriter.class), "writeFieldValue", "(CLjava/lang/String;I)V"); _seperator(mw, context); mw.visitLabel(_end); } private void _int(Class<?> clazz, MethodVisitor mw, FieldInfo property, Context context) { Label _end = new Label(); _nameApply(mw, property, context, _end); _get(mw, context, property); mw.visitVarInsn(ISTORE, context.var("int")); _filters(mw, property, context, _end); mw.visitVarInsn(ALOAD, context.var("out")); mw.visitVarInsn(ILOAD, context.var("seperator")); mw.visitVarInsn(ALOAD, context.fieldName()); mw.visitVarInsn(ILOAD, context.var("int")); mw.visitMethodInsn(INVOKEVIRTUAL, getType(SerializeWriter.class), "writeFieldValue", "(CLjava/lang/String;I)V"); _seperator(mw, context); mw.visitLabel(_end); } private void _decimal(Class<?> clazz, MethodVisitor mw, FieldInfo property, Context context) { Label _end = new Label(); _nameApply(mw, property, context, _end); _get(mw, context, property); mw.visitVarInsn(ASTORE, context.var("decimal")); _filters(mw, property, context, _end); Label _if = new Label(); Label _else = new Label(); Label _end_if = new Label(); mw.visitLabel(_if); // if (decimalValue == null) { mw.visitVarInsn(ALOAD, context.var("decimal")); mw.visitJumpInsn(IFNONNULL, _else); _if_write_null(mw, property, context); mw.visitJumpInsn(GOTO, _end_if); mw.visitLabel(_else); // else { out.writeFieldValue(seperator, fieldName, fieldValue) mw.visitVarInsn(ALOAD, context.var("out")); mw.visitVarInsn(ILOAD, context.var("seperator")); mw.visitVarInsn(ALOAD, context.fieldName()); mw.visitVarInsn(ALOAD, context.var("decimal")); mw.visitMethodInsn(INVOKEVIRTUAL, getType(SerializeWriter.class), "writeFieldValue", "(CLjava/lang/String;Ljava/math/BigDecimal;)V"); _seperator(mw, context); mw.visitJumpInsn(GOTO, _end_if); mw.visitLabel(_end_if); mw.visitLabel(_end); } private void _string(Class<?> clazz, MethodVisitor mw, FieldInfo property, Context context) { Label _end = new Label(); _nameApply(mw, property, context, _end); _get(mw, context, property); mw.visitVarInsn(ASTORE, context.var("string")); _filters(mw, property, context, _end); Label _else = new Label(); Label _end_if = new Label(); // if (value == null) { mw.visitVarInsn(ALOAD, context.var("string")); mw.visitJumpInsn(IFNONNULL, _else); _if_write_null(mw, property, context); mw.visitJumpInsn(GOTO, _end_if); mw.visitLabel(_else); // else { out.writeFieldValue(seperator, fieldName, fieldValue) mw.visitVarInsn(ALOAD, context.var("out")); mw.visitVarInsn(ILOAD, context.var("seperator")); mw.visitVarInsn(ALOAD, context.fieldName()); mw.visitVarInsn(ALOAD, context.var("string")); mw.visitMethodInsn(INVOKEVIRTUAL, getType(SerializeWriter.class), "writeFieldValue", "(CLjava/lang/String;Ljava/lang/String;)V"); _seperator(mw, context); mw.visitLabel(_end_if); mw.visitLabel(_end); } private void _list(Class<?> clazz, MethodVisitor mw, FieldInfo property, Context context) { Type propertyType = property.getFieldType(); Type elementType; if (propertyType instanceof Class) { elementType = Object.class; } else { elementType = ((ParameterizedType) propertyType).getActualTypeArguments()[0]; } Class<?> elementClass = null; if (elementType instanceof Class<?>) { elementClass = (Class<?>) elementType; } Label _end = new Label(); Label _if = new Label(); Label _else = new Label(); Label _end_if = new Label(); mw.visitLabel(_if); _nameApply(mw, property, context, _end); _get(mw, context, property); mw.visitTypeInsn(CHECKCAST, getType(List.class)); // cast mw.visitVarInsn(ASTORE, context.var("list")); _filters(mw, property, context, _end); mw.visitVarInsn(ALOAD, context.var("list")); mw.visitJumpInsn(IFNONNULL, _else); _if_write_null(mw, property, context); mw.visitJumpInsn(GOTO, _end_if); mw.visitLabel(_else); // else { mw.visitVarInsn(ALOAD, context.var("out")); mw.visitVarInsn(ILOAD, context.var("seperator")); mw.visitMethodInsn(INVOKEVIRTUAL, getType(SerializeWriter.class), "write", "(C)V"); mw.visitVarInsn(ALOAD, context.var("out")); mw.visitVarInsn(ALOAD, context.fieldName()); mw.visitMethodInsn(INVOKEVIRTUAL, getType(SerializeWriter.class), "writeFieldName", "(Ljava/lang/String;)V"); // mw.visitVarInsn(ALOAD, context.var("list")); mw.visitMethodInsn(INVOKEINTERFACE, getType(List.class), "size", "()I"); mw.visitVarInsn(ISTORE, context.var("int")); Label _if_3 = new Label(); Label _else_3 = new Label(); Label _end_if_3 = new Label(); mw.visitLabel(_if_3); mw.visitVarInsn(ILOAD, context.var("int")); mw.visitInsn(ICONST_0); mw.visitJumpInsn(IF_ICMPNE, _else_3); mw.visitVarInsn(ALOAD, context.var("out")); mw.visitLdcInsn("[]"); mw.visitMethodInsn(INVOKEVIRTUAL, getType(SerializeWriter.class), "write", "(Ljava/lang/String;)V"); mw.visitJumpInsn(GOTO, _end_if_3); mw.visitLabel(_else_3); { mw.visitVarInsn(ALOAD, context.serializer()); mw.visitVarInsn(ALOAD, context.var("list")); mw.visitVarInsn(ALOAD, context.fieldName()); mw.visitMethodInsn(INVOKEVIRTUAL, getType(JSONSerializer.class), "setContext", "(Ljava/lang/Object;Ljava/lang/Object;)V"); } { mw.visitVarInsn(ALOAD, context.var("out")); mw.visitVarInsn(BIPUSH, '['); mw.visitMethodInsn(INVOKEVIRTUAL, getType(SerializeWriter.class), "write", "(C)V"); // list_serializer = null mw.visitInsn(ACONST_NULL); mw.visitTypeInsn(CHECKCAST, getType(ObjectSerializer.class)); // cast to string mw.visitVarInsn(ASTORE, context.var("list_ser")); Label _for = new Label(); Label _end_for = new Label(); mw.visitInsn(ICONST_0); mw.visitVarInsn(ISTORE, context.var("i")); // for (; i < list.size() -1; ++i) { mw.visitLabel(_for); mw.visitVarInsn(ILOAD, context.var("i")); mw.visitVarInsn(ILOAD, context.var("int")); mw.visitInsn(ICONST_1); mw.visitInsn(ISUB); mw.visitJumpInsn(IF_ICMPGE, _end_for); // i < list.size - 1 if (elementType == String.class) { // out.write((String)list.get(i)); mw.visitVarInsn(ALOAD, context.var("out")); mw.visitVarInsn(ALOAD, context.var("list")); mw.visitVarInsn(ILOAD, context.var("i")); mw.visitMethodInsn(INVOKEINTERFACE, getType(List.class), "get", "(I)Ljava/lang/Object;"); mw.visitTypeInsn(CHECKCAST, getType(String.class)); // cast to string mw.visitVarInsn(BIPUSH, ','); mw.visitMethodInsn(INVOKEVIRTUAL, getType(SerializeWriter.class), "writeString", "(Ljava/lang/String;C)V"); } else { mw.visitVarInsn(ALOAD, context.serializer()); mw.visitVarInsn(ALOAD, context.var("list")); mw.visitVarInsn(ILOAD, context.var("i")); mw.visitMethodInsn(INVOKEINTERFACE, getType(List.class), "get", "(I)Ljava/lang/Object;"); mw.visitVarInsn(ILOAD, context.var("i")); mw.visitMethodInsn(INVOKESTATIC, getType(Integer.class), "valueOf", "(I)Ljava/lang/Integer;"); if (elementClass != null && Modifier.isPublic(elementClass.getModifiers())) { mw.visitLdcInsn(org.objectweb.asm.Type.getType(elementClass)); mw.visitMethodInsn(INVOKEVIRTUAL, getType(JSONSerializer.class), "writeWithFieldName", "(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/reflect/Type;)V"); } else { mw.visitMethodInsn(INVOKEVIRTUAL, getType(JSONSerializer.class), "writeWithFieldName", "(Ljava/lang/Object;Ljava/lang/Object;)V"); } mw.visitVarInsn(ALOAD, context.var("out")); mw.visitVarInsn(BIPUSH, ','); mw.visitMethodInsn(INVOKEVIRTUAL, getType(SerializeWriter.class), "write", "(C)V"); } mw.visitIincInsn(context.var("i"), 1); mw.visitJumpInsn(GOTO, _for); mw.visitLabel(_end_for); if (elementType == String.class) { // out.write((String)list.get(size - 1)); mw.visitVarInsn(ALOAD, context.var("out")); mw.visitVarInsn(ALOAD, context.var("list")); mw.visitVarInsn(ILOAD, context.var("int")); mw.visitInsn(ICONST_1); mw.visitInsn(ISUB); mw.visitMethodInsn(INVOKEINTERFACE, getType(List.class), "get", "(I)Ljava/lang/Object;"); mw.visitTypeInsn(CHECKCAST, getType(String.class)); // cast to string mw.visitVarInsn(BIPUSH, ']'); mw.visitMethodInsn(INVOKEVIRTUAL, getType(SerializeWriter.class), "writeString", "(Ljava/lang/String;C)V"); } else { mw.visitVarInsn(ALOAD, context.serializer()); mw.visitVarInsn(ALOAD, context.var("list")); mw.visitVarInsn(ILOAD, context.var("i")); mw.visitMethodInsn(INVOKEINTERFACE, getType(List.class), "get", "(I)Ljava/lang/Object;"); mw.visitVarInsn(ILOAD, context.var("i")); mw.visitMethodInsn(INVOKESTATIC, getType(Integer.class), "valueOf", "(I)Ljava/lang/Integer;"); if (elementClass != null && Modifier.isPublic(elementClass.getModifiers())) { mw.visitLdcInsn(org.objectweb.asm.Type.getType(elementClass)); mw.visitMethodInsn(INVOKEVIRTUAL, getType(JSONSerializer.class), "writeWithFieldName", "(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/reflect/Type;)V"); } else { mw.visitMethodInsn(INVOKEVIRTUAL, getType(JSONSerializer.class), "writeWithFieldName", "(Ljava/lang/Object;Ljava/lang/Object;)V"); } mw.visitVarInsn(ALOAD, context.var("out")); mw.visitVarInsn(BIPUSH, ']'); mw.visitMethodInsn(INVOKEVIRTUAL, getType(SerializeWriter.class), "write", "(C)V"); } } { mw.visitVarInsn(ALOAD, context.serializer()); mw.visitMethodInsn(INVOKEVIRTUAL, getType(JSONSerializer.class), "popContext", "()V"); } mw.visitLabel(_end_if_3); _seperator(mw, context); mw.visitLabel(_end_if); mw.visitLabel(_end); } private void _filters(MethodVisitor mw, FieldInfo property, Context context, Label _end) { if (property.getField() != null) { if (Modifier.isTransient(property.getField().getModifiers())) { mw.visitVarInsn(ALOAD, context.var("out")); mw.visitFieldInsn(GETSTATIC, getType(SerializerFeature.class), "SkipTransientField", "L" + getType(SerializerFeature.class) + ";"); mw.visitMethodInsn(INVOKEVIRTUAL, getType(SerializeWriter.class), "isEnabled", "(" + "L" + getType(SerializerFeature.class) + ";" + ")Z"); // if true mw.visitJumpInsn(IFNE, _end); } } _apply(mw, property, context); mw.visitJumpInsn(IFEQ, _end); _processKey(mw, property, context); Label _else_processKey = new Label(); _processValue(mw, property, context); mw.visitVarInsn(ALOAD, context.original()); mw.visitVarInsn(ALOAD, context.processValue()); mw.visitJumpInsn(IF_ACMPEQ, _else_processKey); _writeObject(mw, property, context, _end); mw.visitJumpInsn(GOTO, _end); mw.visitLabel(_else_processKey); } private void _nameApply(MethodVisitor mw, FieldInfo property, Context context, Label _end) { mw.visitVarInsn(ALOAD, context.serializer()); mw.visitVarInsn(ALOAD, context.obj()); mw.visitVarInsn(ALOAD, context.fieldName()); mw.visitMethodInsn(INVOKESTATIC, getType(FilterUtils.class), "applyName", "(Lcom/alibaba/fastjson/serializer/JSONSerializer;Ljava/lang/Object;Ljava/lang/String;)Z"); mw.visitJumpInsn(IFEQ, _end); } private void _writeObject(MethodVisitor mw, FieldInfo fieldInfo, Context context, Label _end) { String format = null; JSONField annotation = fieldInfo.getAnnotation(JSONField.class); if (annotation != null) { format = annotation.format(); if (format.trim().length() == 0) { format = null; } } Label _not_null = new Label(); mw.visitVarInsn(ALOAD, context.processValue()); mw.visitJumpInsn(IFNONNULL, _not_null); // if (obj == null) _if_write_null(mw, fieldInfo, context); mw.visitJumpInsn(GOTO, _end); mw.visitLabel(_not_null); // writeFieldNullNumber mw.visitVarInsn(ALOAD, context.var("out")); mw.visitVarInsn(ILOAD, context.var("seperator")); mw.visitMethodInsn(INVOKEVIRTUAL, getType(SerializeWriter.class), "write", "(C)V"); // out.writeFieldName("fieldName") mw.visitVarInsn(ALOAD, context.var("out")); mw.visitVarInsn(ALOAD, context.fieldName()); mw.visitMethodInsn(INVOKEVIRTUAL, getType(SerializeWriter.class), "writeFieldName", "(Ljava/lang/String;)V"); // serializer.write(obj) mw.visitVarInsn(ALOAD, context.serializer()); // serializer mw.visitVarInsn(ALOAD, context.processValue()); if (format != null) { mw.visitLdcInsn(format); mw.visitMethodInsn(INVOKEVIRTUAL, getType(JSONSerializer.class), "writeWithFormat", "(Ljava/lang/Object;Ljava/lang/String;)V"); } else { mw.visitVarInsn(ALOAD, context.fieldName()); if (fieldInfo.getFieldType() instanceof Class<?> && ((Class<?>) fieldInfo.getFieldType()).isPrimitive()) { mw.visitMethodInsn(INVOKEVIRTUAL, getType(JSONSerializer.class), "writeWithFieldName", "(Ljava/lang/Object;Ljava/lang/Object;)V"); } else { // fieldInfo.getName() + "_asm_fieldType" mw.visitVarInsn(ALOAD, 0); mw.visitFieldInsn(GETFIELD, context.getClassName(), fieldInfo.getName() + "_asm_fieldType", "Ljava/lang/reflect/Type;"); mw.visitMethodInsn(INVOKEVIRTUAL, getType(JSONSerializer.class), "writeWithFieldName", "(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/reflect/Type;)V"); } } _seperator(mw, context); } private void _apply(MethodVisitor mw, FieldInfo property, Context context) { Class<?> propertyClass = property.getFieldClass(); mw.visitVarInsn(ALOAD, context.serializer()); mw.visitVarInsn(ALOAD, context.obj()); mw.visitVarInsn(ALOAD, context.fieldName()); if (propertyClass == byte.class) { mw.visitVarInsn(ILOAD, context.var("byte")); mw.visitMethodInsn(INVOKESTATIC, getType(FilterUtils.class), "apply", "(Lcom/alibaba/fastjson/serializer/JSONSerializer;Ljava/lang/Object;Ljava/lang/String;B)Z"); } else if (propertyClass == short.class) { mw.visitVarInsn(ILOAD, context.var("short")); mw.visitMethodInsn(INVOKESTATIC, getType(FilterUtils.class), "apply", "(Lcom/alibaba/fastjson/serializer/JSONSerializer;Ljava/lang/Object;Ljava/lang/String;S)Z"); } else if (propertyClass == int.class) { mw.visitVarInsn(ILOAD, context.var("int")); mw.visitMethodInsn(INVOKESTATIC, getType(FilterUtils.class), "apply", "(Lcom/alibaba/fastjson/serializer/JSONSerializer;Ljava/lang/Object;Ljava/lang/String;I)Z"); } else if (propertyClass == char.class) { mw.visitVarInsn(ILOAD, context.var("char")); mw.visitMethodInsn(INVOKESTATIC, getType(FilterUtils.class), "apply", "(Lcom/alibaba/fastjson/serializer/JSONSerializer;Ljava/lang/Object;Ljava/lang/String;C)Z"); } else if (propertyClass == long.class) { mw.visitVarInsn(LLOAD, context.var("long", 2)); mw.visitMethodInsn(INVOKESTATIC, getType(FilterUtils.class), "apply", "(Lcom/alibaba/fastjson/serializer/JSONSerializer;Ljava/lang/Object;Ljava/lang/String;J)Z"); } else if (propertyClass == float.class) { mw.visitVarInsn(FLOAD, context.var("float")); mw.visitMethodInsn(INVOKESTATIC, getType(FilterUtils.class), "apply", "(Lcom/alibaba/fastjson/serializer/JSONSerializer;Ljava/lang/Object;Ljava/lang/String;F)Z"); } else if (propertyClass == double.class) { mw.visitVarInsn(DLOAD, context.var("double", 2)); mw.visitMethodInsn(INVOKESTATIC, getType(FilterUtils.class), "apply", "(Lcom/alibaba/fastjson/serializer/JSONSerializer;Ljava/lang/Object;Ljava/lang/String;D)Z"); } else if (propertyClass == boolean.class) { mw.visitVarInsn(ILOAD, context.var("boolean")); mw.visitMethodInsn(INVOKESTATIC, getType(FilterUtils.class), "apply", "(Lcom/alibaba/fastjson/serializer/JSONSerializer;Ljava/lang/Object;Ljava/lang/String;B)Z"); } else if (propertyClass == BigDecimal.class) { mw.visitVarInsn(ALOAD, context.var("decimal")); mw.visitMethodInsn(INVOKESTATIC, getType(FilterUtils.class), "apply", "(Lcom/alibaba/fastjson/serializer/JSONSerializer;Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)Z"); } else if (propertyClass == String.class) { mw.visitVarInsn(ALOAD, context.var("string")); mw.visitMethodInsn(INVOKESTATIC, getType(FilterUtils.class), "apply", "(Lcom/alibaba/fastjson/serializer/JSONSerializer;Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)Z"); } else if (propertyClass.isEnum()) { mw.visitVarInsn(ALOAD, context.var("enum")); mw.visitMethodInsn(INVOKESTATIC, getType(FilterUtils.class), "apply", "(Lcom/alibaba/fastjson/serializer/JSONSerializer;Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)Z"); } else if (List.class.isAssignableFrom(propertyClass)) { mw.visitVarInsn(ALOAD, context.var("list")); mw.visitMethodInsn(INVOKESTATIC, getType(FilterUtils.class), "apply", "(Lcom/alibaba/fastjson/serializer/JSONSerializer;Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)Z"); } else { mw.visitVarInsn(ALOAD, context.var("object")); mw.visitMethodInsn(INVOKESTATIC, getType(FilterUtils.class), "apply", "(Lcom/alibaba/fastjson/serializer/JSONSerializer;Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)Z"); } } private void _processValue(MethodVisitor mw, FieldInfo property, Context context) { Class<?> propertyClass = property.getFieldClass(); mw.visitVarInsn(ALOAD, context.serializer()); mw.visitVarInsn(ALOAD, context.obj()); mw.visitVarInsn(ALOAD, context.fieldName()); if (propertyClass == byte.class) { mw.visitVarInsn(ILOAD, context.var("byte")); mw.visitMethodInsn(INVOKESTATIC, getType(Byte.class), "valueOf", "(B)Ljava/lang/Byte;"); } else if (propertyClass == short.class) { mw.visitVarInsn(ILOAD, context.var("short")); mw.visitMethodInsn(INVOKESTATIC, getType(Short.class), "valueOf", "(S)Ljava/lang/Short;"); } else if (propertyClass == int.class) { mw.visitVarInsn(ILOAD, context.var("int")); mw.visitMethodInsn(INVOKESTATIC, getType(Integer.class), "valueOf", "(I)Ljava/lang/Integer;"); } else if (propertyClass == char.class) { mw.visitVarInsn(ILOAD, context.var("char")); mw.visitMethodInsn(INVOKESTATIC, getType(Character.class), "valueOf", "(C)Ljava/lang/Character;"); } else if (propertyClass == long.class) { mw.visitVarInsn(LLOAD, context.var("long", 2)); mw.visitMethodInsn(INVOKESTATIC, getType(Long.class), "valueOf", "(J)Ljava/lang/Long;"); } else if (propertyClass == float.class) { mw.visitVarInsn(FLOAD, context.var("float")); mw.visitMethodInsn(INVOKESTATIC, getType(Float.class), "valueOf", "(F)Ljava/lang/Float;"); } else if (propertyClass == double.class) { mw.visitVarInsn(DLOAD, context.var("double", 2)); mw.visitMethodInsn(INVOKESTATIC, getType(Double.class), "valueOf", "(D)Ljava/lang/Double;"); } else if (propertyClass == boolean.class) { mw.visitVarInsn(ILOAD, context.var("boolean")); mw.visitMethodInsn(INVOKESTATIC, getType(Boolean.class), "valueOf", "(Z)Ljava/lang/Boolean;"); } else if (propertyClass == BigDecimal.class) { mw.visitVarInsn(ALOAD, context.var("decimal")); } else if (propertyClass == String.class) { mw.visitVarInsn(ALOAD, context.var("string")); } else if (propertyClass.isEnum()) { mw.visitVarInsn(ALOAD, context.var("enum")); } else if (List.class.isAssignableFrom(propertyClass)) { mw.visitVarInsn(ALOAD, context.var("list")); } else { mw.visitVarInsn(ALOAD, context.var("object")); } mw.visitVarInsn(ASTORE, context.original()); mw.visitVarInsn(ALOAD, context.original()); mw.visitMethodInsn(INVOKESTATIC, getType(FilterUtils.class), "processValue", "(Lcom/alibaba/fastjson/serializer/JSONSerializer;Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;"); mw.visitVarInsn(ASTORE, context.processValue()); } private void _processKey(MethodVisitor mw, FieldInfo property, Context context) { Class<?> propertyClass = property.getFieldClass(); mw.visitVarInsn(ALOAD, context.serializer()); mw.visitVarInsn(ALOAD, context.obj()); mw.visitVarInsn(ALOAD, context.fieldName()); if (propertyClass == byte.class) { mw.visitVarInsn(ILOAD, context.var("byte")); mw.visitMethodInsn(INVOKESTATIC, getType(FilterUtils.class), "processKey", "(Lcom/alibaba/fastjson/serializer/JSONSerializer;Ljava/lang/Object;Ljava/lang/String;B)Ljava/lang/String;"); } else if (propertyClass == short.class) { mw.visitVarInsn(ILOAD, context.var("short")); mw.visitMethodInsn(INVOKESTATIC, getType(FilterUtils.class), "processKey", "(Lcom/alibaba/fastjson/serializer/JSONSerializer;Ljava/lang/Object;Ljava/lang/String;S)Ljava/lang/String;"); } else if (propertyClass == int.class) { mw.visitVarInsn(ILOAD, context.var("int")); mw.visitMethodInsn(INVOKESTATIC, getType(FilterUtils.class), "processKey", "(Lcom/alibaba/fastjson/serializer/JSONSerializer;Ljava/lang/Object;Ljava/lang/String;I)Ljava/lang/String;"); } else if (propertyClass == char.class) { mw.visitVarInsn(ILOAD, context.var("char")); mw.visitMethodInsn(INVOKESTATIC, getType(FilterUtils.class), "processKey", "(Lcom/alibaba/fastjson/serializer/JSONSerializer;Ljava/lang/Object;Ljava/lang/String;C)Ljava/lang/String;"); } else if (propertyClass == long.class) { mw.visitVarInsn(LLOAD, context.var("long", 2)); mw.visitMethodInsn(INVOKESTATIC, getType(FilterUtils.class), "processKey", "(Lcom/alibaba/fastjson/serializer/JSONSerializer;Ljava/lang/Object;Ljava/lang/String;J)Ljava/lang/String;"); } else if (propertyClass == float.class) { mw.visitVarInsn(FLOAD, context.var("float")); mw.visitMethodInsn(INVOKESTATIC, getType(FilterUtils.class), "processKey", "(Lcom/alibaba/fastjson/serializer/JSONSerializer;Ljava/lang/Object;Ljava/lang/String;F)Ljava/lang/String;"); } else if (propertyClass == double.class) { mw.visitVarInsn(DLOAD, context.var("double", 2)); mw.visitMethodInsn(INVOKESTATIC, getType(FilterUtils.class), "processKey", "(Lcom/alibaba/fastjson/serializer/JSONSerializer;Ljava/lang/Object;Ljava/lang/String;D)Ljava/lang/String;"); } else if (propertyClass == boolean.class) { mw.visitVarInsn(ILOAD, context.var("boolean")); mw.visitMethodInsn(INVOKESTATIC, getType(FilterUtils.class), "processKey", "(Lcom/alibaba/fastjson/serializer/JSONSerializer;Ljava/lang/Object;Ljava/lang/String;Z)Ljava/lang/String;"); } else if (propertyClass == BigDecimal.class) { mw.visitVarInsn(ALOAD, context.var("decimal")); mw.visitMethodInsn(INVOKESTATIC, getType(FilterUtils.class), "processKey", "(Lcom/alibaba/fastjson/serializer/JSONSerializer;Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/String;"); } else if (propertyClass == String.class) { mw.visitVarInsn(ALOAD, context.var("string")); mw.visitMethodInsn(INVOKESTATIC, getType(FilterUtils.class), "processKey", "(Lcom/alibaba/fastjson/serializer/JSONSerializer;Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/String;"); } else if (propertyClass.isEnum()) { mw.visitVarInsn(ALOAD, context.var("enum")); mw.visitMethodInsn(INVOKESTATIC, getType(FilterUtils.class), "processKey", "(Lcom/alibaba/fastjson/serializer/JSONSerializer;Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/String;"); } else if (List.class.isAssignableFrom(propertyClass)) { mw.visitVarInsn(ALOAD, context.var("list")); mw.visitMethodInsn(INVOKESTATIC, getType(FilterUtils.class), "processKey", "(Lcom/alibaba/fastjson/serializer/JSONSerializer;Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/String;"); } else { mw.visitVarInsn(ALOAD, context.var("object")); mw.visitMethodInsn(INVOKESTATIC, getType(FilterUtils.class), "processKey", "(Lcom/alibaba/fastjson/serializer/JSONSerializer;Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/String;"); } mw.visitVarInsn(ASTORE, context.fieldName()); } private void _if_write_null(MethodVisitor mw, FieldInfo fieldInfo, Context context) { Class<?> propertyClass = fieldInfo.getFieldClass(); Label _if = new Label(); Label _else = new Label(); Label _write_null = new Label(); Label _end_if = new Label(); mw.visitLabel(_if); // out.isEnabled(Serializer.WriteMapNullValue) boolean writeNull = false; boolean writeNullNumberAsZero = false; boolean writeNullStringAsEmpty = false; boolean writeNullBooleanAsFalse = false; boolean writeNullListAsEmpty = false; JSONField annotation = fieldInfo.getAnnotation(JSONField.class); if (annotation != null) { for (SerializerFeature feature : annotation.serialzeFeatures()) { if (feature == SerializerFeature.WriteMapNullValue) { writeNull = true; } else if (feature == SerializerFeature.WriteNullNumberAsZero) { writeNullNumberAsZero = true; } else if (feature == SerializerFeature.WriteNullStringAsEmpty) { writeNullStringAsEmpty = true; } else if (feature == SerializerFeature.WriteNullBooleanAsFalse) { writeNullBooleanAsFalse = true; } else if (feature == SerializerFeature.WriteNullListAsEmpty) { writeNullListAsEmpty = true; } } } if (!writeNull) { mw.visitVarInsn(ALOAD, context.var("out")); mw.visitFieldInsn(GETSTATIC, getType(SerializerFeature.class), "WriteMapNullValue", "L" + getType(SerializerFeature.class) + ";"); mw.visitMethodInsn(INVOKEVIRTUAL, getType(SerializeWriter.class), "isEnabled", "(" + "L" + getType(SerializerFeature.class) + ";" + ")Z"); mw.visitJumpInsn(IFEQ, _else); } mw.visitLabel(_write_null); // out.writeFieldNull(seperator, 'fieldName') mw.visitVarInsn(ALOAD, context.var("out")); mw.visitVarInsn(ILOAD, context.var("seperator")); mw.visitVarInsn(ALOAD, context.fieldName()); if (propertyClass == String.class || propertyClass == Character.class) { if (writeNullStringAsEmpty) { mw.visitLdcInsn(""); mw.visitMethodInsn(INVOKEVIRTUAL, getType(SerializeWriter.class), "writeFieldValue", "(CLjava/lang/String;Ljava/lang/String;)V"); } else { mw.visitMethodInsn(INVOKEVIRTUAL, getType(SerializeWriter.class), "writeFieldNullString", "(CLjava/lang/String;)V"); } } else if (Number.class.isAssignableFrom(propertyClass)) { if (writeNullNumberAsZero) { mw.visitInsn(ICONST_0); mw.visitMethodInsn(INVOKEVIRTUAL, getType(SerializeWriter.class), "writeFieldValue", "(CLjava/lang/String;I)V"); } else { mw.visitMethodInsn(INVOKEVIRTUAL, getType(SerializeWriter.class), "writeFieldNullNumber", "(CLjava/lang/String;)V"); } } else if (propertyClass == Boolean.class) { if (writeNullBooleanAsFalse) { mw.visitInsn(ICONST_0); mw.visitMethodInsn(INVOKEVIRTUAL, getType(SerializeWriter.class), "writeFieldValue", "(CLjava/lang/String;Z)V"); } else { mw.visitMethodInsn(INVOKEVIRTUAL, getType(SerializeWriter.class), "writeFieldNullBoolean", "(CLjava/lang/String;)V"); } } else if (Collection.class.isAssignableFrom(propertyClass) || propertyClass.isArray()) { if (writeNullListAsEmpty) { mw.visitMethodInsn(INVOKEVIRTUAL, getType(SerializeWriter.class), "writeFieldEmptyList", "(CLjava/lang/String;)V"); } else { mw.visitMethodInsn(INVOKEVIRTUAL, getType(SerializeWriter.class), "writeFieldNullList", "(CLjava/lang/String;)V"); } } else { mw.visitMethodInsn(INVOKEVIRTUAL, getType(SerializeWriter.class), "writeFieldNull", "(CLjava/lang/String;)V"); } // seperator = ','; _seperator(mw, context); mw.visitJumpInsn(GOTO, _end_if); mw.visitLabel(_else); mw.visitLabel(_end_if); } private void _seperator(MethodVisitor mw, Context context) { mw.visitVarInsn(BIPUSH, ','); mw.visitVarInsn(ISTORE, context.var("seperator")); } }