com.alibaba.fastjson.serializer.ASMSerializerFactory Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of fastjson-to-easyjson Show documentation
Show all versions of fastjson-to-easyjson Show documentation
Adapter alibaba fastjson to other json libraries. the fastjson version: 1.2.58
/*
* Copyright 2019 the original author or authors.
*
* Licensed under the Apache, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.gnu.org/licenses/lgpl-3.0.html
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.fastjson.serializer;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.annotation.JSONField;
import com.alibaba.fastjson.annotation.JSONType;
import com.alibaba.fastjson.asm.*;
import com.alibaba.fastjson.parser.ParserConfig;
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 java.io.Serializable;
import java.lang.reflect.*;
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 static com.alibaba.fastjson.util.ASMUtils.desc;
import static com.alibaba.fastjson.util.ASMUtils.type;
public class ASMSerializerFactory implements Opcodes {
static final String JSONSerializer = type(JSONSerializer.class);
static final String ObjectSerializer = type(ObjectSerializer.class);
static final String ObjectSerializer_desc = "L" + ObjectSerializer + ";";
static final String SerializeWriter = type(SerializeWriter.class);
static final String SerializeWriter_desc = "L" + SerializeWriter + ";";
static final String JavaBeanSerializer = type(JavaBeanSerializer.class);
static final String JavaBeanSerializer_desc = "L" + type(JavaBeanSerializer.class) + ";";
static final String SerialContext_desc = desc(SerialContext.class);
static final String SerializeFilterable_desc = desc(SerializeFilterable.class);
protected final ASMClassLoader classLoader = new ASMClassLoader();
private final AtomicLong seed = new AtomicLong();
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;
}
String packageName = ASMSerializerFactory.class.getPackage().getName();
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, "", "(" + desc(SerializeBeanInfo.class) + ")V", null, null);
mw.visitVarInsn(ALOAD, 0);
mw.visitVarInsn(ALOAD, 1);
mw.visitMethodInsn(INVOKESPECIAL, JavaBeanSerializer, "", "(" + 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;
}
}
}
// 0 write
// 1 writeNormal
// 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);
}
mw.visitVarInsn(ALOAD, Context.obj); // obj
mw.visitTypeInsn(CHECKCAST, type(clazz)); // serializer
mw.visitVarInsn(ASTORE, context.var("entity")); // obj
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"));
mw.visitVarInsn(ALOAD, Context.obj); // obj
mw.visitTypeInsn(CHECKCAST, type(clazz)); // serializer
mw.visitVarInsn(ASTORE, context.var("entity")); // obj
generateWriteMethod(clazz, mw, unsortedGetters, context);
mw.visitInsn(RETURN);
mw.visitMaxs(7, context.variantIndex + 2);
mw.visitEnd();
}
// 0 writeAsArray
// 1 writeAsArrayNormal
// 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"));
mw.visitVarInsn(ALOAD, Context.obj); // obj
mw.visitTypeInsn(CHECKCAST, type(clazz)); // serializer
mw.visitVarInsn(ASTORE, context.var("entity")); // obj
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;
}
private void generateWriteAsArray(Class> clazz, MethodVisitor mw, FieldInfo[] getters,
Context context) throws Exception {
Label nonPropertyFilters_ = new Label();
mw.visitVarInsn(ALOAD, Context.serializer);
mw.visitVarInsn(ALOAD, 0);
mw.visitMethodInsn(INVOKEVIRTUAL, JSONSerializer, "hasPropertyFilters", "(" + SerializeFilterable_desc + ")Z");
mw.visitJumpInsn(IFNE, nonPropertyFilters_);
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(INVOKESPECIAL, JavaBeanSerializer,
"writeNoneASM", "(L" + JSONSerializer
+ ";Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/reflect/Type;I)V");
mw.visitInsn(RETURN);
mw.visitLabel(nonPropertyFilters_);
mw.visitVarInsn(ALOAD, context.var("out"));
mw.visitVarInsn(BIPUSH, '[');
mw.visitMethodInsn(INVOKEVIRTUAL, SerializeWriter, "write", "(I)V");
int size = getters.length;
if (size == 0) {
mw.visitVarInsn(ALOAD, context.var("out"));
mw.visitVarInsn(BIPUSH, ']');
mw.visitMethodInsn(INVOKEVIRTUAL, SerializeWriter, "write", "(I)V");
return;
}
for (int i = 0; i < size; ++i) {
final char seperator = (i == size - 1) ? ']' : ',';
FieldInfo fieldInfo = getters[i];
Class> fieldClass = fieldInfo.fieldClass;
mw.visitLdcInsn(fieldInfo.name);
mw.visitVarInsn(ASTORE, Context.fieldName);
if (fieldClass == byte.class //
|| fieldClass == short.class //
|| fieldClass == int.class) {
mw.visitVarInsn(ALOAD, context.var("out"));
mw.visitInsn(DUP);
_get(mw, context, fieldInfo);
mw.visitMethodInsn(INVOKEVIRTUAL, SerializeWriter, "writeInt", "(I)V");
mw.visitVarInsn(BIPUSH, seperator);
mw.visitMethodInsn(INVOKEVIRTUAL, SerializeWriter, "write", "(I)V");
} else if (fieldClass == long.class) {
mw.visitVarInsn(ALOAD, context.var("out"));
mw.visitInsn(DUP);
_get(mw, context, fieldInfo);
mw.visitMethodInsn(INVOKEVIRTUAL, SerializeWriter, "writeLong", "(J)V");
mw.visitVarInsn(BIPUSH, seperator);
mw.visitMethodInsn(INVOKEVIRTUAL, SerializeWriter, "write", "(I)V");
} else if (fieldClass == float.class) {
mw.visitVarInsn(ALOAD, context.var("out"));
mw.visitInsn(DUP);
_get(mw, context, fieldInfo);
mw.visitInsn(ICONST_1);
mw.visitMethodInsn(INVOKEVIRTUAL, SerializeWriter, "writeFloat", "(FZ)V");
mw.visitVarInsn(BIPUSH, seperator);
mw.visitMethodInsn(INVOKEVIRTUAL, SerializeWriter, "write", "(I)V");
} else if (fieldClass == double.class) {
mw.visitVarInsn(ALOAD, context.var("out"));
mw.visitInsn(DUP);
_get(mw, context, fieldInfo);
mw.visitInsn(ICONST_1);
mw.visitMethodInsn(INVOKEVIRTUAL, SerializeWriter, "writeDouble", "(DZ)V");
mw.visitVarInsn(BIPUSH, seperator);
mw.visitMethodInsn(INVOKEVIRTUAL, SerializeWriter, "write", "(I)V");
} else if (fieldClass == boolean.class) {
mw.visitVarInsn(ALOAD, context.var("out"));
mw.visitInsn(DUP);
_get(mw, context, fieldInfo);
mw.visitMethodInsn(INVOKEVIRTUAL, SerializeWriter, "write", "(Z)V");
mw.visitVarInsn(BIPUSH, seperator);
mw.visitMethodInsn(INVOKEVIRTUAL, SerializeWriter, "write", "(I)V");
} else if (fieldClass == char.class) {
mw.visitVarInsn(ALOAD, context.var("out"));
_get(mw, context, fieldInfo); // Character.toString(value)
mw.visitMethodInsn(INVOKESTATIC, "java/lang/Character", "toString", "(C)Ljava/lang/String;");
mw.visitVarInsn(BIPUSH, seperator);
mw.visitMethodInsn(INVOKEVIRTUAL, SerializeWriter, "writeString", "(Ljava/lang/String;C)V");
} else if (fieldClass == String.class) {
mw.visitVarInsn(ALOAD, context.var("out"));
_get(mw, context, fieldInfo);
mw.visitVarInsn(BIPUSH, seperator);
mw.visitMethodInsn(INVOKEVIRTUAL, SerializeWriter, "writeString", "(Ljava/lang/String;C)V");
} else if (fieldClass.isEnum()) {
mw.visitVarInsn(ALOAD, context.var("out"));
mw.visitInsn(DUP);
_get(mw, context, fieldInfo);
mw.visitMethodInsn(INVOKEVIRTUAL, SerializeWriter, "writeEnum", "(Ljava/lang/Enum;)V");
mw.visitVarInsn(BIPUSH, seperator);
mw.visitMethodInsn(INVOKEVIRTUAL, SerializeWriter, "write", "(I)V");
} else if (List.class.isAssignableFrom(fieldClass)) {
Type fieldType = fieldInfo.fieldType;
Type elementType;
if (fieldType instanceof Class) {
elementType = Object.class;
} else {
elementType = ((ParameterizedType) fieldType).getActualTypeArguments()[0];
}
Class> elementClass = null;
if (elementType instanceof Class>) {
elementClass = (Class>) elementType;
if (elementClass == Object.class) {
elementClass = null;
}
}
_get(mw, context, fieldInfo);
mw.visitTypeInsn(CHECKCAST, "java/util/List"); // cast
mw.visitVarInsn(ASTORE, context.var("list"));
if (elementClass == String.class //
&& context.writeDirect) {
mw.visitVarInsn(ALOAD, context.var("out"));
mw.visitVarInsn(ALOAD, context.var("list"));
mw.visitMethodInsn(INVOKEVIRTUAL, SerializeWriter, "write", "(Ljava/util/List;)V");
} else {
Label nullEnd_ = new Label(), nullElse_ = new Label();
mw.visitVarInsn(ALOAD, context.var("list"));
mw.visitJumpInsn(IFNONNULL, nullElse_);
mw.visitVarInsn(ALOAD, context.var("out"));
mw.visitMethodInsn(INVOKEVIRTUAL, SerializeWriter, "writeNull", "()V");
mw.visitJumpInsn(GOTO, nullEnd_);
mw.visitLabel(nullElse_);
mw.visitVarInsn(ALOAD, context.var("list"));
mw.visitMethodInsn(INVOKEINTERFACE, "java/util/List", "size", "()I");
mw.visitVarInsn(ISTORE, context.var("size"));
mw.visitVarInsn(ALOAD, context.var("out"));
mw.visitVarInsn(BIPUSH, '[');
mw.visitMethodInsn(INVOKEVIRTUAL, SerializeWriter, "write", "(I)V");
Label for_ = new Label(), forFirst_ = new Label(), forEnd_ = 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("size"));
mw.visitJumpInsn(IF_ICMPGE, forEnd_); // i < list.size - 1
mw.visitVarInsn(ILOAD, context.var("i"));
mw.visitJumpInsn(IFEQ, forFirst_); // i < list.size - 1
mw.visitVarInsn(ALOAD, context.var("out"));
mw.visitVarInsn(BIPUSH, ',');
mw.visitMethodInsn(INVOKEVIRTUAL, SerializeWriter, "write", "(I)V");
mw.visitLabel(forFirst_);
mw.visitVarInsn(ALOAD, context.var("list"));
mw.visitVarInsn(ILOAD, context.var("i"));
mw.visitMethodInsn(INVOKEINTERFACE, "java/util/List", "get", "(I)Ljava/lang/Object;");
mw.visitVarInsn(ASTORE, context.var("list_item"));
Label forItemNullEnd_ = new Label(), forItemNullElse_ = new Label();
mw.visitVarInsn(ALOAD, context.var("list_item"));
mw.visitJumpInsn(IFNONNULL, forItemNullElse_);
mw.visitVarInsn(ALOAD, context.var("out"));
mw.visitMethodInsn(INVOKEVIRTUAL, SerializeWriter, "writeNull", "()V");
mw.visitJumpInsn(GOTO, forItemNullEnd_);
mw.visitLabel(forItemNullElse_);
Label forItemClassIfEnd_ = new Label(), forItemClassIfElse_ = new Label();
if (elementClass != null && Modifier.isPublic(elementClass.getModifiers())) {
mw.visitVarInsn(ALOAD, context.var("list_item"));
mw.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;");
mw.visitLdcInsn(com.alibaba.fastjson.asm.Type.getType(desc(elementClass)));
mw.visitJumpInsn(IF_ACMPNE, forItemClassIfElse_);
_getListFieldItemSer(context, mw, fieldInfo, elementClass);
mw.visitVarInsn(ASTORE, context.var("list_item_desc"));
Label instanceOfElse_ = new Label(), instanceOfEnd_ = new Label();
if (context.writeDirect) {
mw.visitVarInsn(ALOAD, context.var("list_item_desc"));
mw.visitTypeInsn(INSTANCEOF, JavaBeanSerializer);
mw.visitJumpInsn(IFEQ, instanceOfElse_);
mw.visitVarInsn(ALOAD, context.var("list_item_desc"));
mw.visitTypeInsn(CHECKCAST, JavaBeanSerializer); // cast
mw.visitVarInsn(ALOAD, Context.serializer);
mw.visitVarInsn(ALOAD, context.var("list_item")); // object
if (context.nonContext) { // fieldName
mw.visitInsn(ACONST_NULL);
} else {
mw.visitVarInsn(ILOAD, context.var("i"));
mw.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf",
"(I)Ljava/lang/Integer;");
}
mw.visitLdcInsn(com.alibaba.fastjson.asm.Type.getType(desc(elementClass))); // fieldType
mw.visitLdcInsn(fieldInfo.serialzeFeatures); // features
mw.visitMethodInsn(INVOKEVIRTUAL, JavaBeanSerializer, "writeAsArrayNonContext", //
"(L" + JSONSerializer + ";Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/reflect/Type;I)V");
mw.visitJumpInsn(GOTO, instanceOfEnd_);
mw.visitLabel(instanceOfElse_);
}
mw.visitVarInsn(ALOAD, context.var("list_item_desc"));
mw.visitVarInsn(ALOAD, Context.serializer);
mw.visitVarInsn(ALOAD, context.var("list_item")); // object
if (context.nonContext) { // fieldName
mw.visitInsn(ACONST_NULL);
} else {
mw.visitVarInsn(ILOAD, context.var("i"));
mw.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;");
}
mw.visitLdcInsn(com.alibaba.fastjson.asm.Type.getType(desc(elementClass))); // fieldType
mw.visitLdcInsn(fieldInfo.serialzeFeatures); // features
mw.visitMethodInsn(INVOKEINTERFACE, ObjectSerializer, "write", //
"(L" + JSONSerializer + ";Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/reflect/Type;I)V");
mw.visitLabel(instanceOfEnd_);
mw.visitJumpInsn(GOTO, forItemClassIfEnd_);
}
mw.visitLabel(forItemClassIfElse_);
mw.visitVarInsn(ALOAD, Context.serializer);
mw.visitVarInsn(ALOAD, context.var("list_item"));
if (context.nonContext) {
mw.visitInsn(ACONST_NULL);
} else {
mw.visitVarInsn(ILOAD, context.var("i"));
mw.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;");
}
if (elementClass != null && Modifier.isPublic(elementClass.getModifiers())) {
mw.visitLdcInsn(com.alibaba.fastjson.asm.Type.getType(desc((Class>) elementType)));
mw.visitLdcInsn(fieldInfo.serialzeFeatures);
mw.visitMethodInsn(INVOKEVIRTUAL, JSONSerializer, "writeWithFieldName",
"(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/reflect/Type;I)V");
} else {
mw.visitMethodInsn(INVOKEVIRTUAL, JSONSerializer, "writeWithFieldName",
"(Ljava/lang/Object;Ljava/lang/Object;)V");
}
mw.visitLabel(forItemClassIfEnd_);
mw.visitLabel(forItemNullEnd_);
mw.visitIincInsn(context.var("i"), 1);
mw.visitJumpInsn(GOTO, for_);
mw.visitLabel(forEnd_);
mw.visitVarInsn(ALOAD, context.var("out"));
mw.visitVarInsn(BIPUSH, ']');
mw.visitMethodInsn(INVOKEVIRTUAL, SerializeWriter, "write", "(I)V");
mw.visitLabel(nullEnd_);
}
mw.visitVarInsn(ALOAD, context.var("out"));
mw.visitVarInsn(BIPUSH, seperator);
mw.visitMethodInsn(INVOKEVIRTUAL, SerializeWriter, "write", "(I)V");
} else {
Label notNullEnd_ = new Label(), notNullElse_ = new Label();
_get(mw, context, fieldInfo);
mw.visitInsn(DUP);
mw.visitVarInsn(ASTORE, context.var("field_" + fieldInfo.fieldClass.getName()));
mw.visitJumpInsn(IFNONNULL, notNullElse_);
mw.visitVarInsn(ALOAD, context.var("out"));
mw.visitMethodInsn(INVOKEVIRTUAL, SerializeWriter, "writeNull", "()V");
mw.visitJumpInsn(GOTO, notNullEnd_);
mw.visitLabel(notNullElse_);
Label classIfEnd_ = new Label(), classIfElse_ = new Label();
mw.visitVarInsn(ALOAD, context.var("field_" + fieldInfo.fieldClass.getName()));
mw.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;");
mw.visitLdcInsn(com.alibaba.fastjson.asm.Type.getType(desc(fieldClass)));
mw.visitJumpInsn(IF_ACMPNE, classIfElse_);
_getFieldSer(context, mw, fieldInfo);
mw.visitVarInsn(ASTORE, context.var("fied_ser"));
Label instanceOfElse_ = new Label(), instanceOfEnd_ = new Label();
if (context.writeDirect && Modifier.isPublic(fieldClass.getModifiers())) {
mw.visitVarInsn(ALOAD, context.var("fied_ser"));
mw.visitTypeInsn(INSTANCEOF, JavaBeanSerializer);
mw.visitJumpInsn(IFEQ, instanceOfElse_);
mw.visitVarInsn(ALOAD, context.var("fied_ser"));
mw.visitTypeInsn(CHECKCAST, JavaBeanSerializer); // cast
mw.visitVarInsn(ALOAD, Context.serializer);
mw.visitVarInsn(ALOAD, context.var("field_" + fieldInfo.fieldClass.getName()));
mw.visitVarInsn(ALOAD, Context.fieldName);
mw.visitLdcInsn(com.alibaba.fastjson.asm.Type.getType(desc(fieldClass))); // fieldType
mw.visitLdcInsn(fieldInfo.serialzeFeatures); // features
mw.visitMethodInsn(INVOKEVIRTUAL, JavaBeanSerializer, "writeAsArrayNonContext", //
"(L" + JSONSerializer + ";Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/reflect/Type;I)V");
mw.visitJumpInsn(GOTO, instanceOfEnd_);
mw.visitLabel(instanceOfElse_);
}
mw.visitVarInsn(ALOAD, context.var("fied_ser"));
mw.visitVarInsn(ALOAD, Context.serializer);
mw.visitVarInsn(ALOAD, context.var("field_" + fieldInfo.fieldClass.getName()));
mw.visitVarInsn(ALOAD, Context.fieldName);
mw.visitLdcInsn(com.alibaba.fastjson.asm.Type.getType(desc(fieldClass))); // fieldType
mw.visitLdcInsn(fieldInfo.serialzeFeatures); // features
mw.visitMethodInsn(INVOKEINTERFACE, ObjectSerializer, "write", //
"(L" + JSONSerializer + ";Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/reflect/Type;I)V");
mw.visitLabel(instanceOfEnd_);
mw.visitJumpInsn(GOTO, classIfEnd_);
mw.visitLabel(classIfElse_);
String format = fieldInfo.getFormat();
mw.visitVarInsn(ALOAD, Context.serializer);
mw.visitVarInsn(ALOAD, context.var("field_" + fieldInfo.fieldClass.getName()));
if (format != null) {
mw.visitLdcInsn(format);
mw.visitMethodInsn(INVOKEVIRTUAL, JSONSerializer, "writeWithFormat",
"(Ljava/lang/Object;Ljava/lang/String;)V");
} else {
mw.visitVarInsn(ALOAD, Context.fieldName);
if (fieldInfo.fieldType instanceof Class> //
&& ((Class>) fieldInfo.fieldType).isPrimitive()) {
mw.visitMethodInsn(INVOKEVIRTUAL, JSONSerializer, "writeWithFieldName",
"(Ljava/lang/Object;Ljava/lang/Object;)V");
} else {
mw.visitVarInsn(ALOAD, 0); // this
mw.visitFieldInsn(GETFIELD, context.className, fieldInfo.name + "_asm_fieldType",
"Ljava/lang/reflect/Type;");
mw.visitLdcInsn(fieldInfo.serialzeFeatures);
mw.visitMethodInsn(INVOKEVIRTUAL, JSONSerializer, "writeWithFieldName",
"(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/reflect/Type;I)V");
}
}
mw.visitLabel(classIfEnd_);
mw.visitLabel(notNullEnd_);
mw.visitVarInsn(ALOAD, context.var("out"));
mw.visitVarInsn(BIPUSH, seperator);
mw.visitMethodInsn(INVOKEVIRTUAL, SerializeWriter, "write", "(I)V");
}
}
}
private void generateWriteMethod(Class> clazz, MethodVisitor mw, FieldInfo[] getters,
Context context) throws Exception {
// if (serializer.containsReference(object)) {
Label end = new Label();
int size = getters.length;
if (!context.writeDirect) {
// pretty format not byte code optimized
Label endSupper_ = new Label();
Label supper_ = new Label();
mw.visitVarInsn(ALOAD, context.var("out"));
mw.visitLdcInsn(SerializerFeature.PrettyFormat.mask);
mw.visitMethodInsn(INVOKEVIRTUAL, SerializeWriter, "isEnabled", "(I)Z");
mw.visitJumpInsn(IFNE, supper_);
boolean hasMethod = false;
for (FieldInfo getter : getters) {
if (getter.method != null) {
hasMethod = true;
}
}
if (hasMethod) {
mw.visitVarInsn(ALOAD, context.var("out"));
mw.visitLdcInsn(SerializerFeature.IgnoreErrorGetter.mask);
mw.visitMethodInsn(INVOKEVIRTUAL, SerializeWriter, "isEnabled", "(I)Z");
mw.visitJumpInsn(IFEQ, endSupper_);
} else {
mw.visitJumpInsn(GOTO, endSupper_);
}
mw.visitLabel(supper_);
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(INVOKESPECIAL, JavaBeanSerializer,
"write", "(L" + JSONSerializer
+ ";Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/reflect/Type;I)V");
mw.visitInsn(RETURN);
mw.visitLabel(endSupper_);
}
if (!context.nonContext) {
Label endRef_ = new Label();
// /////
mw.visitVarInsn(ALOAD, 0); // this
mw.visitVarInsn(ALOAD, Context.serializer);
mw.visitVarInsn(ALOAD, Context.obj);
mw.visitVarInsn(ILOAD, Context.features);
mw.visitMethodInsn(INVOKEVIRTUAL, JavaBeanSerializer, "writeReference",
"(L" + JSONSerializer + ";Ljava/lang/Object;I)Z");
mw.visitJumpInsn(IFEQ, endRef_);
mw.visitInsn(RETURN);
mw.visitLabel(endRef_);
}
final String writeAsArrayMethodName;
if (context.writeDirect) {
if (context.nonContext) {
writeAsArrayMethodName = "writeAsArrayNonContext";
} else {
writeAsArrayMethodName = "writeAsArray";
}
} else {
writeAsArrayMethodName = "writeAsArrayNormal";
}
if ((context.beanInfo.features & SerializerFeature.BeanToArray.mask) == 0) {
Label endWriteAsArray_ = new Label();
mw.visitVarInsn(ALOAD, context.var("out"));
mw.visitLdcInsn(SerializerFeature.BeanToArray.mask);
mw.visitMethodInsn(INVOKEVIRTUAL, SerializeWriter, "isEnabled", "(I)Z");
mw.visitJumpInsn(IFEQ, endWriteAsArray_);
// /////
mw.visitVarInsn(ALOAD, 0); // this
mw.visitVarInsn(ALOAD, Context.serializer);
mw.visitVarInsn(ALOAD, 2); // obj
mw.visitVarInsn(ALOAD, 3); // fieldObj
mw.visitVarInsn(ALOAD, 4); // fieldType
mw.visitVarInsn(ILOAD, 5); // features
mw.visitMethodInsn(INVOKEVIRTUAL, //
context.className, //
writeAsArrayMethodName, //
"(L" + JSONSerializer + ";Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/reflect/Type;I)V");
mw.visitInsn(RETURN);
mw.visitLabel(endWriteAsArray_);
} else {
mw.visitVarInsn(ALOAD, 0); // this
mw.visitVarInsn(ALOAD, Context.serializer);
mw.visitVarInsn(ALOAD, 2); // obj
mw.visitVarInsn(ALOAD, 3); // fieldObj
mw.visitVarInsn(ALOAD, 4); // fieldType
mw.visitVarInsn(ILOAD, 5); // features
mw.visitMethodInsn(INVOKEVIRTUAL, //
context.className, //
writeAsArrayMethodName, //
"(L" + JSONSerializer + ";Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/reflect/Type;I)V");
mw.visitInsn(RETURN);
}
if (!context.nonContext) {
mw.visitVarInsn(ALOAD, Context.serializer);
mw.visitMethodInsn(INVOKEVIRTUAL, JSONSerializer, "getContext", "()" + SerialContext_desc);
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.visitLdcInsn(context.beanInfo.features);
mw.visitMethodInsn(INVOKEVIRTUAL, JSONSerializer, "setContext",
"(" + SerialContext_desc + "Ljava/lang/Object;Ljava/lang/Object;I)V");
}
boolean writeClasName = (context.beanInfo.features & SerializerFeature.WriteClassName.mask) != 0;
// SEPERATO
if (writeClasName || !context.writeDirect) {
Label end_ = new Label();
Label else_ = new Label();
Label writeClass_ = new Label();
if (!writeClasName) {
mw.visitVarInsn(ALOAD, Context.serializer);
mw.visitVarInsn(ALOAD, Context.paramFieldType);
mw.visitVarInsn(ALOAD, Context.obj);
mw.visitMethodInsn(INVOKEVIRTUAL, JSONSerializer, "isWriteClassName",
"(Ljava/lang/reflect/Type;Ljava/lang/Object;)Z");
mw.visitJumpInsn(IFEQ, else_);
}
// IFNULL
mw.visitVarInsn(ALOAD, Context.paramFieldType);
mw.visitVarInsn(ALOAD, Context.obj);
mw.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;");
mw.visitJumpInsn(IF_ACMPEQ, else_);
mw.visitLabel(writeClass_);
mw.visitVarInsn(ALOAD, context.var("out"));
mw.visitVarInsn(BIPUSH, '{');
mw.visitMethodInsn(INVOKEVIRTUAL, SerializeWriter, "write", "(I)V");
mw.visitVarInsn(ALOAD, 0);
mw.visitVarInsn(ALOAD, Context.serializer);
if (context.beanInfo.typeKey != null) {
mw.visitLdcInsn(context.beanInfo.typeKey);
} else {
mw.visitInsn(ACONST_NULL);
}
mw.visitVarInsn(ALOAD, Context.obj);
mw.visitMethodInsn(INVOKEVIRTUAL, JavaBeanSerializer, "writeClassName", "(L" + JSONSerializer + ";Ljava/lang/String;Ljava/lang/Object;)V");
mw.visitVarInsn(BIPUSH, ',');
mw.visitJumpInsn(GOTO, end_);
mw.visitLabel(else_);
mw.visitVarInsn(BIPUSH, '{');
mw.visitLabel(end_);
} else {
mw.visitVarInsn(BIPUSH, '{');
}
mw.visitVarInsn(ISTORE, context.var("seperator"));
if (!context.writeDirect) {
_before(mw, context);
}
if (!context.writeDirect) {
mw.visitVarInsn(ALOAD, context.var("out"));
mw.visitMethodInsn(INVOKEVIRTUAL, SerializeWriter, "isNotWriteDefaultValue", "()Z");
mw.visitVarInsn(ISTORE, context.var("notWriteDefaultValue"));
mw.visitVarInsn(ALOAD, Context.serializer);
mw.visitVarInsn(ALOAD, 0);
mw.visitMethodInsn(INVOKEVIRTUAL, JSONSerializer, "checkValue", "(" + SerializeFilterable_desc + ")Z");
mw.visitVarInsn(ISTORE, context.var("checkValue"));
mw.visitVarInsn(ALOAD, Context.serializer);
mw.visitVarInsn(ALOAD, 0);
mw.visitMethodInsn(INVOKEVIRTUAL, JSONSerializer, "hasNameFilters", "(" + SerializeFilterable_desc + ")Z");
mw.visitVarInsn(ISTORE, context.var("hasNameFilters"));
}
for (int i = 0; i < size; ++i) {
FieldInfo property = getters[i];
Class> propertyClass = property.fieldClass;
mw.visitLdcInsn(property.name);
mw.visitVarInsn(ASTORE, Context.fieldName);
if (propertyClass == byte.class //
|| propertyClass == short.class //
|| propertyClass == int.class) {
_int(clazz, mw, property, context, context.var(propertyClass.getName()), 'I');
} 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) {
_int(clazz, mw, property, context, context.var("boolean"), 'Z');
} else if (propertyClass == char.class) {
_int(clazz, mw, property, context, context.var("char"), 'C');
} 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);
} else if (propertyClass.isEnum()) {
_enum(clazz, mw, property, context);
} else {
_object(clazz, mw, property, context);
}
}
if (!context.writeDirect) {
_after(mw, context);
}
Label _else = new Label();
Label _end_if = new Label();
mw.visitVarInsn(ILOAD, context.var("seperator"));
mw.visitIntInsn(BIPUSH, '{');
mw.visitJumpInsn(IF_ICMPNE, _else);
mw.visitVarInsn(ALOAD, context.var("out"));
mw.visitVarInsn(BIPUSH, '{');
mw.visitMethodInsn(INVOKEVIRTUAL, SerializeWriter, "write", "(I)V");
mw.visitLabel(_else);
mw.visitVarInsn(ALOAD, context.var("out"));
mw.visitVarInsn(BIPUSH, '}');
mw.visitMethodInsn(INVOKEVIRTUAL, SerializeWriter, "write", "(I)V");
mw.visitLabel(_end_if);
mw.visitLabel(end);
if (!context.nonContext) {
mw.visitVarInsn(ALOAD, Context.serializer);
mw.visitVarInsn(ALOAD, context.var("parent"));
mw.visitMethodInsn(INVOKEVIRTUAL, JSONSerializer, "setContext", "(" + SerialContext_desc + ")V");
}
}
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 fieldInfo, Context context) {
Label _not_null = new Label();
Label _end_if = new Label();
Label _end = new Label();
_nameApply(mw, fieldInfo, context, _end);
_get(mw, context, fieldInfo);
mw.visitTypeInsn(CHECKCAST, "java/lang/Enum"); // cast
mw.visitVarInsn(ASTORE, context.var("enum"));
_filters(mw, fieldInfo, context, _end);
mw.visitVarInsn(ALOAD, context.var("enum"));
mw.visitJumpInsn(IFNONNULL, _not_null);
_if_write_null(mw, fieldInfo, context);
mw.visitJumpInsn(GOTO, _end_if);
mw.visitLabel(_not_null);
if (context.writeDirect) {
mw.visitVarInsn(ALOAD, context.var("out"));
mw.visitVarInsn(ILOAD, context.var("seperator"));
mw.visitVarInsn(ALOAD, Context.fieldName);
mw.visitVarInsn(ALOAD, context.var("enum"));
mw.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Enum", "name", "()Ljava/lang/String;");
mw.visitMethodInsn(INVOKEVIRTUAL, SerializeWriter, "writeFieldValueStringWithDoubleQuote",
"(CLjava/lang/String;Ljava/lang/String;)V");
} else {
mw.visitVarInsn(ALOAD, context.var("out"));
mw.visitVarInsn(ILOAD, context.var("seperator"));
mw.visitMethodInsn(INVOKEVIRTUAL, SerializeWriter, "write", "(I)V");
mw.visitVarInsn(ALOAD, context.var("out"));
mw.visitVarInsn(ALOAD, Context.fieldName);
mw.visitInsn(ICONST_0);
mw.visitMethodInsn(INVOKEVIRTUAL, SerializeWriter, "writeFieldName", "(Ljava/lang/String;Z)V");
mw.visitVarInsn(ALOAD, Context.serializer);
mw.visitVarInsn(ALOAD, context.var("enum"));
mw.visitVarInsn(ALOAD, Context.fieldName);
mw.visitLdcInsn(com.alibaba.fastjson.asm.Type.getType(desc((Class>) fieldInfo.fieldClass)));
mw.visitLdcInsn(fieldInfo.serialzeFeatures);
mw.visitMethodInsn(INVOKEVIRTUAL, JSONSerializer, "writeWithFieldName",
"(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/reflect/Type;I)V");
}
_seperator(mw, context);
mw.visitLabel(_end_if);
mw.visitLabel(_end);
}
private void _int(Class> clazz, MethodVisitor mw, FieldInfo property, Context context, int var, char type) {
Label end_ = new Label();
_nameApply(mw, property, context, end_);
_get(mw, context, property);
mw.visitVarInsn(ISTORE, var);
_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, var);
mw.visitMethodInsn(INVOKEVIRTUAL, SerializeWriter, "writeFieldValue", "(CLjava/lang/String;" + type + ")V");
_seperator(mw, context);
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, SerializeWriter, "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, SerializeWriter, "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, SerializeWriter, "writeFieldValue", "(CLjava/lang/String;D)V");
_seperator(mw, context);
mw.visitLabel(end_);
}
private void _get(MethodVisitor mw, Context context, FieldInfo fieldInfo) {
Method method = fieldInfo.method;
if (method != null) {
mw.visitVarInsn(ALOAD, context.var("entity"));
Class> declaringClass = method.getDeclaringClass();
mw.visitMethodInsn(declaringClass.isInterface() ? INVOKEINTERFACE : INVOKEVIRTUAL, type(declaringClass), method.getName(), desc(method));
if (!method.getReturnType().equals(fieldInfo.fieldClass)) {
mw.visitTypeInsn(CHECKCAST, type(fieldInfo.fieldClass)); // cast
}
} else {
mw.visitVarInsn(ALOAD, context.var("entity"));
Field field = fieldInfo.field;
mw.visitFieldInsn(GETFIELD, type(fieldInfo.declaringClass), field.getName(),
desc(field.getType()));
if (!field.getType().equals(fieldInfo.fieldClass)) {
mw.visitTypeInsn(CHECKCAST, type(fieldInfo.fieldClass)); // cast
}
}
}
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 endIf_ = 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, endIf_);
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, SerializeWriter, "writeFieldValue",
"(CLjava/lang/String;Ljava/math/BigDecimal;)V");
_seperator(mw, context);
mw.visitJumpInsn(GOTO, endIf_);
mw.visitLabel(endIf_);
mw.visitLabel(end_);
}
private void _string(Class> clazz, MethodVisitor mw, FieldInfo property, Context context) {
Label end_ = new Label();
if (property.name.equals(context.beanInfo.typeKey)) {
mw.visitVarInsn(ALOAD, Context.serializer);
mw.visitVarInsn(ALOAD, Context.paramFieldType);
mw.visitVarInsn(ALOAD, Context.obj);
mw.visitMethodInsn(INVOKEVIRTUAL, JSONSerializer, "isWriteClassName",
"(Ljava/lang/reflect/Type;Ljava/lang/Object;)Z");
mw.visitJumpInsn(IFNE, end_);
}
_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 endIf_ = new Label();
// if (value == null) {
mw.visitVarInsn(ALOAD, context.var("string"));
mw.visitJumpInsn(IFNONNULL, else_);
_if_write_null(mw, property, context);
mw.visitJumpInsn(GOTO, endIf_);
mw.visitLabel(else_); // else { out.writeFieldValue(seperator, fieldName, fieldValue)
if ("trim".equals(property.format)) {
mw.visitVarInsn(ALOAD, context.var("string"));
mw.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "trim", "()Ljava/lang/String;");
mw.visitVarInsn(ASTORE, context.var("string"));
}
if (context.writeDirect) {
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, SerializeWriter, "writeFieldValueStringWithDoubleQuoteCheck",
"(CLjava/lang/String;Ljava/lang/String;)V");
} else {
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, SerializeWriter, "writeFieldValue",
"(CLjava/lang/String;Ljava/lang/String;)V");
}
_seperator(mw, context);
mw.visitLabel(endIf_);
mw.visitLabel(end_);
}
private void _list(Class> clazz, MethodVisitor mw, FieldInfo fieldInfo, Context context) {
Type propertyType = fieldInfo.fieldType;
Type elementType = TypeUtils.getCollectionItemType(propertyType);
Class> elementClass = null;
if (elementType instanceof Class>) {
elementClass = (Class>) elementType;
}
if (elementClass == Object.class //
|| elementClass == Serializable.class) {
elementClass = null;
}
Label end_ = new Label(), else_ = new Label(), endIf_ = new Label();
_nameApply(mw, fieldInfo, context, end_);
_get(mw, context, fieldInfo);
mw.visitTypeInsn(CHECKCAST, "java/util/List"); // cast
mw.visitVarInsn(ASTORE, context.var("list"));
_filters(mw, fieldInfo, context, end_);
mw.visitVarInsn(ALOAD, context.var("list"));
mw.visitJumpInsn(IFNONNULL, else_);
_if_write_null(mw, fieldInfo, context);
mw.visitJumpInsn(GOTO, endIf_);
mw.visitLabel(else_); // else {
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("list"));
mw.visitMethodInsn(INVOKEINTERFACE, "java/util/List", "size", "()I");
mw.visitVarInsn(ISTORE, context.var("size"));
Label _else_3 = new Label();
Label _end_if_3 = new Label();
mw.visitVarInsn(ILOAD, context.var("size"));
mw.visitInsn(ICONST_0);
mw.visitJumpInsn(IF_ICMPNE, _else_3);
mw.visitVarInsn(ALOAD, context.var("out"));
mw.visitLdcInsn("[]");
mw.visitMethodInsn(INVOKEVIRTUAL, SerializeWriter, "write", "(Ljava/lang/String;)V");
mw.visitJumpInsn(GOTO, _end_if_3);
mw.visitLabel(_else_3);
if (!context.nonContext) {
mw.visitVarInsn(ALOAD, Context.serializer);
mw.visitVarInsn(ALOAD, context.var("list"));
mw.visitVarInsn(ALOAD, Context.fieldName);
mw.visitMethodInsn(INVOKEVIRTUAL, JSONSerializer, "setContext", "(Ljava/lang/Object;Ljava/lang/Object;)V");
}
if (elementType == String.class //
&& context.writeDirect) {
mw.visitVarInsn(ALOAD, context.var("out"));
mw.visitVarInsn(ALOAD, context.var("list"));
mw.visitMethodInsn(INVOKEVIRTUAL, SerializeWriter, "write", "(Ljava/util/List;)V");
} else {
mw.visitVarInsn(ALOAD, context.var("out"));
mw.visitVarInsn(BIPUSH, '[');
mw.visitMethodInsn(INVOKEVIRTUAL, SerializeWriter, "write", "(I)V");
Label for_ = new Label(), forFirst_ = new Label(), forEnd_ = 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("size"));
mw.visitJumpInsn(IF_ICMPGE, forEnd_); // i < list.size - 1
mw.visitVarInsn(ILOAD, context.var("i"));
mw.visitJumpInsn(IFEQ, forFirst_); // i < list.size - 1
mw.visitVarInsn(ALOAD, context.var("out"));
mw.visitVarInsn(BIPUSH, ',');
mw.visitMethodInsn(INVOKEVIRTUAL, SerializeWriter, "write", "(I)V");
mw.visitLabel(forFirst_);
mw.visitVarInsn(ALOAD, context.var("list"));
mw.visitVarInsn(ILOAD, context.var("i"));
mw.visitMethodInsn(INVOKEINTERFACE, "java/util/List", "get", "(I)Ljava/lang/Object;");
mw.visitVarInsn(ASTORE, context.var("list_item"));
Label forItemNullEnd_ = new Label(), forItemNullElse_ = new Label();
mw.visitVarInsn(ALOAD, context.var("list_item"));
mw.visitJumpInsn(IFNONNULL, forItemNullElse_);
mw.visitVarInsn(ALOAD, context.var("out"));
mw.visitMethodInsn(INVOKEVIRTUAL, SerializeWriter, "writeNull", "()V");
mw.visitJumpInsn(GOTO, forItemNullEnd_);
mw.visitLabel(forItemNullElse_);
Label forItemClassIfEnd_ = new Label(), forItemClassIfElse_ = new Label();
if (elementClass != null && Modifier.isPublic(elementClass.getModifiers())) {
mw.visitVarInsn(ALOAD, context.var("list_item"));
mw.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;");
mw.visitLdcInsn(com.alibaba.fastjson.asm.Type.getType(desc(elementClass)));
mw.visitJumpInsn(IF_ACMPNE, forItemClassIfElse_);
_getListFieldItemSer(context, mw, fieldInfo, elementClass);
// mw.visitInsn(DUP);
mw.visitVarInsn(ASTORE, context.var("list_item_desc"));
Label instanceOfElse_ = new Label(), instanceOfEnd_ = new Label();
if (context.writeDirect) {
String writeMethodName = context.nonContext && context.writeDirect ? //
"writeDirectNonContext" //
: "write";
mw.visitVarInsn(ALOAD, context.var("list_item_desc"));
mw.visitTypeInsn(INSTANCEOF, JavaBeanSerializer);
mw.visitJumpInsn(IFEQ, instanceOfElse_);
mw.visitVarInsn(ALOAD, context.var("list_item_desc"));
mw.visitTypeInsn(CHECKCAST, JavaBeanSerializer); // cast
mw.visitVarInsn(ALOAD, Context.serializer);
mw.visitVarInsn(ALOAD, context.var("list_item")); // object
if (context.nonContext) { // fieldName
mw.visitInsn(ACONST_NULL);
} else {
mw.visitVarInsn(ILOAD, context.var("i"));
mw.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;");
}
mw.visitLdcInsn(com.alibaba.fastjson.asm.Type.getType(desc(elementClass))); // fieldType
mw.visitLdcInsn(fieldInfo.serialzeFeatures); // features
mw.visitMethodInsn(INVOKEVIRTUAL, JavaBeanSerializer, writeMethodName, //
"(L" + JSONSerializer + ";Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/reflect/Type;I)V");
mw.visitJumpInsn(GOTO, instanceOfEnd_);
mw.visitLabel(instanceOfElse_);
}
mw.visitVarInsn(ALOAD, context.var("list_item_desc"));
mw.visitVarInsn(ALOAD, Context.serializer);
mw.visitVarInsn(ALOAD, context.var("list_item")); // object
if (context.nonContext) { // fieldName
mw.visitInsn(ACONST_NULL);
} else {
mw.visitVarInsn(ILOAD, context.var("i"));
mw.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;");
}
mw.visitLdcInsn(com.alibaba.fastjson.asm.Type.getType(desc(elementClass))); // fieldType
mw.visitLdcInsn(fieldInfo.serialzeFeatures); // features
mw.visitMethodInsn(INVOKEINTERFACE, ObjectSerializer, "write", //
"(L" + JSONSerializer + ";Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/reflect/Type;I)V");
mw.visitLabel(instanceOfEnd_);
mw.visitJumpInsn(GOTO, forItemClassIfEnd_);
}
mw.visitLabel(forItemClassIfElse_);
mw.visitVarInsn(ALOAD, Context.serializer);
mw.visitVarInsn(ALOAD, context.var("list_item"));
if (context.nonContext) {
mw.visitInsn(ACONST_NULL);
} else {
mw.visitVarInsn(ILOAD, context.var("i"));
mw.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;");
}
if (elementClass != null && Modifier.isPublic(elementClass.getModifiers())) {
mw.visitLdcInsn(com.alibaba.fastjson.asm.Type.getType(desc((Class>) elementType)));
mw.visitLdcInsn(fieldInfo.serialzeFeatures);
mw.visitMethodInsn(INVOKEVIRTUAL, JSONSerializer, "writeWithFieldName",
"(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/reflect/Type;I)V");
} else {
mw.visitMethodInsn(INVOKEVIRTUAL, JSONSerializer, "writeWithFieldName",
"(Ljava/lang/Object;Ljava/lang/Object;)V");
}
mw.visitLabel(forItemClassIfEnd_);
mw.visitLabel(forItemNullEnd_);
mw.visitIincInsn(context.var("i"), 1);
mw.visitJumpInsn(GOTO, for_);
mw.visitLabel(forEnd_);
mw.visitVarInsn(ALOAD, context.var("out"));
mw.visitVarInsn(BIPUSH, ']');
mw.visitMethodInsn(INVOKEVIRTUAL, SerializeWriter, "write", "(I)V");
}
{
mw.visitVarInsn(ALOAD, Context.serializer);
mw.visitMethodInsn(INVOKEVIRTUAL, JSONSerializer, "popContext", "()V");
}
mw.visitLabel(_end_if_3);
_seperator(mw, context);
mw.visitLabel(endIf_);
mw.visitLabel(end_);
}
private void _filters(MethodVisitor mw, FieldInfo property, Context context, Label _end) {
if (property.fieldTransient) {
mw.visitVarInsn(ALOAD, context.var("out"));
mw.visitLdcInsn(SerializerFeature.SkipTransientField.mask);
mw.visitMethodInsn(INVOKEVIRTUAL, SerializeWriter, "isEnabled", "(I)Z");
mw.visitJumpInsn(IFNE, _end);
}
_notWriteDefault(mw, property, context, _end);
if (context.writeDirect) {
return;
}
_apply(mw, property, context);
mw.visitJumpInsn(IFEQ, _end);
_processKey(mw, property, context);
_processValue(mw, property, context, _end);
}
private void _nameApply(MethodVisitor mw, FieldInfo property, Context context, Label _end) {
if (!context.writeDirect) {
mw.visitVarInsn(ALOAD, 0);
mw.visitVarInsn(ALOAD, Context.serializer);
mw.visitVarInsn(ALOAD, Context.obj);
mw.visitVarInsn(ALOAD, Context.fieldName);
mw.visitMethodInsn(INVOKEVIRTUAL, JavaBeanSerializer, "applyName",
"(L" + JSONSerializer + ";Ljava/lang/Object;Ljava/lang/String;)Z");
mw.visitJumpInsn(IFEQ, _end);
_labelApply(mw, property, context, _end);
}
if (property.field == null) {
mw.visitVarInsn(ALOAD, context.var("out"));
mw.visitLdcInsn(SerializerFeature.IgnoreNonFieldGetter.mask);
mw.visitMethodInsn(INVOKEVIRTUAL, SerializeWriter, "isEnabled", "(I)Z");
// if true
mw.visitJumpInsn(IFNE, _end);
}
}
private void _labelApply(MethodVisitor mw, FieldInfo property, Context context, Label _end) {
mw.visitVarInsn(ALOAD, 0); // this
mw.visitVarInsn(ALOAD, Context.serializer);
mw.visitLdcInsn(property.label);
mw.visitMethodInsn(INVOKEVIRTUAL, JavaBeanSerializer, "applyLabel",
"(L" + JSONSerializer + ";Ljava/lang/String;)Z");
mw.visitJumpInsn(IFEQ, _end);
}
private void _writeObject(MethodVisitor mw, FieldInfo fieldInfo, Context context, Label _end) {
String format = fieldInfo.getFormat();
Class> fieldClass = fieldInfo.fieldClass;
Label notNull_ = new Label();
// if (obj == null)
if (context.writeDirect) {
mw.visitVarInsn(ALOAD, context.var("object"));
} else {
mw.visitVarInsn(ALOAD, Context.processValue);
}
mw.visitInsn(DUP);
mw.visitVarInsn(ASTORE, context.var("object"));
mw.visitJumpInsn(IFNONNULL, notNull_);
_if_write_null(mw, fieldInfo, context);
mw.visitJumpInsn(GOTO, _end);
mw.visitLabel(notNull_);
mw.visitVarInsn(ALOAD, context.var("out"));
mw.visitVarInsn(ILOAD, context.var("seperator"));
mw.visitMethodInsn(INVOKEVIRTUAL, SerializeWriter, "write", "(I)V");
_writeFieldName(mw, context);
Label classIfEnd_ = new Label(), classIfElse_ = new Label();
if (Modifier.isPublic(fieldClass.getModifiers()) //
&& !ParserConfig.isPrimitive2(fieldClass) //
) {
mw.visitVarInsn(ALOAD, context.var("object"));
mw.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;");
mw.visitLdcInsn(com.alibaba.fastjson.asm.Type.getType(desc(fieldClass)));
mw.visitJumpInsn(IF_ACMPNE, classIfElse_);
_getFieldSer(context, mw, fieldInfo);
mw.visitVarInsn(ASTORE, context.var("fied_ser"));
Label instanceOfElse_ = new Label(), instanceOfEnd_ = new Label();
mw.visitVarInsn(ALOAD, context.var("fied_ser"));
mw.visitTypeInsn(INSTANCEOF, JavaBeanSerializer);
mw.visitJumpInsn(IFEQ, instanceOfElse_);
boolean disableCircularReferenceDetect = (fieldInfo.serialzeFeatures & SerializerFeature.DisableCircularReferenceDetect.mask) != 0;
boolean fieldBeanToArray = (fieldInfo.serialzeFeatures & SerializerFeature.BeanToArray.mask) != 0;
String writeMethodName;
if (disableCircularReferenceDetect || (context.nonContext && context.writeDirect)) {
writeMethodName = fieldBeanToArray ? "writeAsArrayNonContext" : "writeDirectNonContext";
} else {
writeMethodName = fieldBeanToArray ? "writeAsArray" : "write";
}
mw.visitVarInsn(ALOAD, context.var("fied_ser"));
mw.visitTypeInsn(CHECKCAST, JavaBeanSerializer); // cast
mw.visitVarInsn(ALOAD, Context.serializer);
mw.visitVarInsn(ALOAD, context.var("object"));
mw.visitVarInsn(ALOAD, Context.fieldName);
mw.visitVarInsn(ALOAD, 0);
mw.visitFieldInsn(GETFIELD, context.className, fieldInfo.name + "_asm_fieldType",
"Ljava/lang/reflect/Type;");
mw.visitLdcInsn(fieldInfo.serialzeFeatures); // features
mw.visitMethodInsn(INVOKEVIRTUAL, JavaBeanSerializer, writeMethodName, //
"(L" + JSONSerializer + ";Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/reflect/Type;I)V");
mw.visitJumpInsn(GOTO, instanceOfEnd_);
mw.visitLabel(instanceOfElse_);
mw.visitVarInsn(ALOAD, context.var("fied_ser"));
mw.visitVarInsn(ALOAD, Context.serializer);
mw.visitVarInsn(ALOAD, context.var("object"));
mw.visitVarInsn(ALOAD, Context.fieldName);
mw.visitVarInsn(ALOAD, 0);
mw.visitFieldInsn(GETFIELD, context.className, fieldInfo.name + "_asm_fieldType",
"Ljava/lang/reflect/Type;");
mw.visitLdcInsn(fieldInfo.serialzeFeatures); // features
mw.visitMethodInsn(INVOKEINTERFACE, ObjectSerializer, "write", //
"(L" + JSONSerializer + ";Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/reflect/Type;I)V");
mw.visitLabel(instanceOfEnd_);
mw.visitJumpInsn(GOTO, classIfEnd_);
}
mw.visitLabel(classIfElse_);
mw.visitVarInsn(ALOAD, Context.serializer);
if (context.writeDirect) {
mw.visitVarInsn(ALOAD, context.var("object"));
} else {
mw.visitVarInsn(ALOAD, Context.processValue);
}
if (format != null) {
mw.visitLdcInsn(format);
mw.visitMethodInsn(INVOKEVIRTUAL, JSONSerializer, "writeWithFormat",
"(Ljava/lang/Object;Ljava/lang/String;)V");
} else {
mw.visitVarInsn(ALOAD, Context.fieldName);
if (fieldInfo.fieldType instanceof Class> //
&& ((Class>) fieldInfo.fieldType).isPrimitive()) {
mw.visitMethodInsn(INVOKEVIRTUAL, JSONSerializer, "writeWithFieldName",
"(Ljava/lang/Object;Ljava/lang/Object;)V");
} else {
if (fieldInfo.fieldClass == String.class) {
mw.visitLdcInsn(com.alibaba.fastjson.asm.Type.getType(desc(String.class)));
} else {
mw.visitVarInsn(ALOAD, 0);
mw.visitFieldInsn(GETFIELD, context.className, fieldInfo.name + "_asm_fieldType",
"Ljava/lang/reflect/Type;");
}
mw.visitLdcInsn(fieldInfo.serialzeFeatures);
mw.visitMethodInsn(INVOKEVIRTUAL, JSONSerializer, "writeWithFieldName",
"(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/reflect/Type;I)V");
}
}
mw.visitLabel(classIfEnd_);
_seperator(mw, context);
}
private void _before(MethodVisitor mw, Context context) {
mw.visitVarInsn(ALOAD, 0); // this
mw.visitVarInsn(ALOAD, Context.serializer);
mw.visitVarInsn(ALOAD, Context.obj);
mw.visitVarInsn(ILOAD, context.var("seperator"));
mw.visitMethodInsn(INVOKEVIRTUAL, JavaBeanSerializer, "writeBefore",
"(L" + JSONSerializer + ";Ljava/lang/Object;C)C");
mw.visitVarInsn(ISTORE, context.var("seperator"));
}
private void _after(MethodVisitor mw, Context context) {
mw.visitVarInsn(ALOAD, 0); // this
mw.visitVarInsn(ALOAD, Context.serializer);
mw.visitVarInsn(ALOAD, 2); // obj
mw.visitVarInsn(ILOAD, context.var("seperator"));
mw.visitMethodInsn(INVOKEVIRTUAL, JavaBeanSerializer, "writeAfter",
"(L" + JSONSerializer + ";Ljava/lang/Object;C)C");
mw.visitVarInsn(ISTORE, context.var("seperator"));
}
private void _notWriteDefault(MethodVisitor mw, FieldInfo property, Context context, Label _end) {
if (context.writeDirect) {
return;
}
Label elseLabel = new Label();
mw.visitVarInsn(ILOAD, context.var("notWriteDefaultValue"));
mw.visitJumpInsn(IFEQ, elseLabel);
Class> propertyClass = property.fieldClass;
if (propertyClass == boolean.class) {
mw.visitVarInsn(ILOAD, context.var("boolean"));
mw.visitJumpInsn(IFEQ, _end);
} else if (propertyClass == byte.class) {
mw.visitVarInsn(ILOAD, context.var("byte"));
mw.visitJumpInsn(IFEQ, _end);
} else if (propertyClass == short.class) {
mw.visitVarInsn(ILOAD, context.var("short"));
mw.visitJumpInsn(IFEQ, _end);
} else if (propertyClass == int.class) {
mw.visitVarInsn(ILOAD, context.var("int"));
mw.visitJumpInsn(IFEQ, _end);
} else if (propertyClass == long.class) {
mw.visitVarInsn(LLOAD, context.var("long"));
mw.visitInsn(LCONST_0);
mw.visitInsn(LCMP);
mw.visitJumpInsn(IFEQ, _end);
} else if (propertyClass == float.class) {
mw.visitVarInsn(FLOAD, context.var("float"));
mw.visitInsn(FCONST_0);
mw.visitInsn(FCMPL);
mw.visitJumpInsn(IFEQ, _end);
} else if (propertyClass == double.class) {
mw.visitVarInsn(DLOAD, context.var("double"));
mw.visitInsn(DCONST_0);
mw.visitInsn(DCMPL);
mw.visitJumpInsn(IFEQ, _end);
}
mw.visitLabel(elseLabel);
}
private void _apply(MethodVisitor mw, FieldInfo property, Context context) {
Class> propertyClass = property.fieldClass;
mw.visitVarInsn(ALOAD, 0); // this
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, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;");
} else if (propertyClass == short.class) {
mw.visitVarInsn(ILOAD, context.var("short"));
mw.visitMethodInsn(INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;");
} else if (propertyClass == int.class) {
mw.visitVarInsn(ILOAD, context.var("int"));
mw.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;");
} else if (propertyClass == char.class) {
mw.visitVarInsn(ILOAD, context.var("char"));
mw.visitMethodInsn(INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;");
} else if (propertyClass == long.class) {
mw.visitVarInsn(LLOAD, context.var("long", 2));
mw.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;");
} else if (propertyClass == float.class) {
mw.visitVarInsn(FLOAD, context.var("float"));
mw.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;");
} else if (propertyClass == double.class) {
mw.visitVarInsn(DLOAD, context.var("double", 2));
mw.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;");
} else if (propertyClass == boolean.class) {
mw.visitVarInsn(ILOAD, context.var("boolean"));
mw.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "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.visitMethodInsn(INVOKEVIRTUAL, JavaBeanSerializer,
"apply", "(L" + JSONSerializer
+ ";Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)Z");
}
private void _processValue(MethodVisitor mw, FieldInfo fieldInfo, Context context, Label _end) {
Label processKeyElse_ = new Label();
Class> fieldClass = fieldInfo.fieldClass;
if (fieldClass.isPrimitive()) {
Label checkValueEnd_ = new Label();
mw.visitVarInsn(ILOAD, context.var("checkValue"));
mw.visitJumpInsn(IFNE, checkValueEnd_);
mw.visitInsn(ACONST_NULL);
mw.visitInsn(DUP);
mw.visitVarInsn(ASTORE, Context.original);
mw.visitVarInsn(ASTORE, Context.processValue);
mw.visitJumpInsn(GOTO, processKeyElse_);
mw.visitLabel(checkValueEnd_);
}
mw.visitVarInsn(ALOAD, 0);
mw.visitVarInsn(ALOAD, Context.serializer);
mw.visitVarInsn(ALOAD, 0);
mw.visitLdcInsn(context.getFieldOrinal(fieldInfo.name));
mw.visitMethodInsn(INVOKEVIRTUAL, JavaBeanSerializer, "getBeanContext", "(I)" + desc(BeanContext.class));
mw.visitVarInsn(ALOAD, Context.obj);
mw.visitVarInsn(ALOAD, Context.fieldName);
String valueDesc = "Ljava/lang/Object;";
if (fieldClass == byte.class) {
mw.visitVarInsn(ILOAD, context.var("byte"));
mw.visitMethodInsn(INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;");
mw.visitInsn(DUP);
mw.visitVarInsn(ASTORE, Context.original);
} else if (fieldClass == short.class) {
mw.visitVarInsn(ILOAD, context.var("short"));
mw.visitMethodInsn(INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;");
mw.visitInsn(DUP);
mw.visitVarInsn(ASTORE, Context.original);
} else if (fieldClass == int.class) {
mw.visitVarInsn(ILOAD, context.var("int"));
mw.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;");
mw.visitInsn(DUP);
mw.visitVarInsn(ASTORE, Context.original);
} else if (fieldClass == char.class) {
mw.visitVarInsn(ILOAD, context.var("char"));
mw.visitMethodInsn(INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;");
mw.visitInsn(DUP);
mw.visitVarInsn(ASTORE, Context.original);
} else if (fieldClass == long.class) {
mw.visitVarInsn(LLOAD, context.var("long", 2));
mw.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;");
mw.visitInsn(DUP);
mw.visitVarInsn(ASTORE, Context.original);
} else if (fieldClass == float.class) {
mw.visitVarInsn(FLOAD, context.var("float"));
mw.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;");
mw.visitInsn(DUP);
mw.visitVarInsn(ASTORE, Context.original);
} else if (fieldClass == double.class) {
mw.visitVarInsn(DLOAD, context.var("double", 2));
mw.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;");
mw.visitInsn(DUP);
mw.visitVarInsn(ASTORE, Context.original);
} else if (fieldClass == boolean.class) {
mw.visitVarInsn(ILOAD, context.var("boolean"));
mw.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;");
mw.visitInsn(DUP);
mw.visitVarInsn(ASTORE, Context.original);
} else if (fieldClass == BigDecimal.class) {
mw.visitVarInsn(ALOAD, context.var("decimal"));
mw.visitVarInsn(ASTORE, Context.original);
mw.visitVarInsn(ALOAD, Context.original);
} else if (fieldClass == String.class) {
mw.visitVarInsn(ALOAD, context.var("string"));
mw.visitVarInsn(ASTORE, Context.original);
mw.visitVarInsn(ALOAD, Context.original);
} else if (fieldClass.isEnum()) {
mw.visitVarInsn(ALOAD, context.var("enum"));
mw.visitVarInsn(ASTORE, Context.original);
mw.visitVarInsn(ALOAD, Context.original);
} else if (List.class.isAssignableFrom(fieldClass)) {
mw.visitVarInsn(ALOAD, context.var("list"));
mw.visitVarInsn(ASTORE, Context.original);
mw.visitVarInsn(ALOAD, Context.original);
} else {
mw.visitVarInsn(ALOAD, context.var("object"));
mw.visitVarInsn(ASTORE, Context.original);
mw.visitVarInsn(ALOAD, Context.original);
}
mw.visitMethodInsn(INVOKEVIRTUAL, JavaBeanSerializer, "processValue",
"(L" + JSONSerializer + ";" //
+ desc(BeanContext.class) //
+ "Ljava/lang/Object;Ljava/lang/String;" //
+ valueDesc + ")Ljava/lang/Object;");
mw.visitVarInsn(ASTORE, Context.processValue);
mw.visitVarInsn(ALOAD, Context.original);
mw.visitVarInsn(ALOAD, Context.processValue);
mw.visitJumpInsn(IF_ACMPEQ, processKeyElse_);
_writeObject(mw, fieldInfo, context, _end);
mw.visitJumpInsn(GOTO, _end);
mw.visitLabel(processKeyElse_);
}
private void _processKey(MethodVisitor mw, FieldInfo property, Context context) {
Label _else_processKey = new Label();
mw.visitVarInsn(ILOAD, context.var("hasNameFilters"));
mw.visitJumpInsn(IFEQ, _else_processKey);
Class> propertyClass = property.fieldClass;
mw.visitVarInsn(ALOAD, 0);
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, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;");
} else if (propertyClass == short.class) {
mw.visitVarInsn(ILOAD, context.var("short"));
mw.visitMethodInsn(INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;");
} else if (propertyClass == int.class) {
mw.visitVarInsn(ILOAD, context.var("int"));
mw.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;");
} else if (propertyClass == char.class) {
mw.visitVarInsn(ILOAD, context.var("char"));
mw.visitMethodInsn(INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;");
} else if (propertyClass == long.class) {
mw.visitVarInsn(LLOAD, context.var("long", 2));
mw.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;");
} else if (propertyClass == float.class) {
mw.visitVarInsn(FLOAD, context.var("float"));
mw.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;");
} else if (propertyClass == double.class) {
mw.visitVarInsn(DLOAD, context.var("double", 2));
mw.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;");
} else if (propertyClass == boolean.class) {
mw.visitVarInsn(ILOAD, context.var("boolean"));
mw.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "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.visitMethodInsn(INVOKEVIRTUAL, JavaBeanSerializer,
"processKey", "(L" + JSONSerializer
+ ";Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/String;");
mw.visitVarInsn(ASTORE, Context.fieldName);
mw.visitLabel(_else_processKey);
}
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);
// 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);
}
private void _writeFieldName(MethodVisitor mw, Context context) {
if (context.writeDirect) {
mw.visitVarInsn(ALOAD, context.var("out"));
mw.visitVarInsn(ALOAD, Context.fieldName);
mw.visitMethodInsn(INVOKEVIRTUAL, SerializeWriter, "writeFieldNameDirect", "(Ljava/lang/String;)V");
} else {
mw.visitVarInsn(ALOAD, context.var("out"));
mw.visitVarInsn(ALOAD, Context.fieldName);
mw.visitInsn(ICONST_0);
mw.visitMethodInsn(INVOKEVIRTUAL, SerializeWriter, "writeFieldName", "(Ljava/lang/String;Z)V");
}
}
private void _seperator(MethodVisitor mw, Context context) {
mw.visitVarInsn(BIPUSH, ',');
mw.visitVarInsn(ISTORE, context.var("seperator"));
}
private void _getListFieldItemSer(Context context, MethodVisitor mw, FieldInfo fieldInfo, Class> itemType) {
Label notNull_ = new Label();
mw.visitVarInsn(ALOAD, 0);
mw.visitFieldInsn(GETFIELD, context.className, fieldInfo.name + "_asm_list_item_ser_",
ObjectSerializer_desc);
mw.visitJumpInsn(IFNONNULL, notNull_);
mw.visitVarInsn(ALOAD, 0); // this
mw.visitVarInsn(ALOAD, Context.serializer);
mw.visitLdcInsn(com.alibaba.fastjson.asm.Type.getType(desc(itemType)));
mw.visitMethodInsn(INVOKEVIRTUAL, JSONSerializer, "getObjectWriter",
"(Ljava/lang/Class;)" + ObjectSerializer_desc);
mw.visitFieldInsn(PUTFIELD, context.className, fieldInfo.name + "_asm_list_item_ser_",
ObjectSerializer_desc);
mw.visitLabel(notNull_);
mw.visitVarInsn(ALOAD, 0);
mw.visitFieldInsn(GETFIELD, context.className, fieldInfo.name + "_asm_list_item_ser_",
ObjectSerializer_desc);
}
private void _getFieldSer(Context context, MethodVisitor mw, FieldInfo fieldInfo) {
Label notNull_ = new Label();
mw.visitVarInsn(ALOAD, 0);
mw.visitFieldInsn(GETFIELD, context.className, fieldInfo.name + "_asm_ser_", ObjectSerializer_desc);
mw.visitJumpInsn(IFNONNULL, notNull_);
mw.visitVarInsn(ALOAD, 0); // this
mw.visitVarInsn(ALOAD, Context.serializer);
mw.visitLdcInsn(com.alibaba.fastjson.asm.Type.getType(desc(fieldInfo.fieldClass)));
mw.visitMethodInsn(INVOKEVIRTUAL, JSONSerializer, "getObjectWriter",
"(Ljava/lang/Class;)" + ObjectSerializer_desc);
mw.visitFieldInsn(PUTFIELD, context.className, fieldInfo.name + "_asm_ser_", ObjectSerializer_desc);
mw.visitLabel(notNull_);
mw.visitVarInsn(ALOAD, 0);
mw.visitFieldInsn(GETFIELD, context.className, fieldInfo.name + "_asm_ser_", ObjectSerializer_desc);
}
static class Context {
static final int serializer = 1;
static final int obj = 2;
static final int paramFieldName = 3;
static final int paramFieldType = 4;
static final int features = 5;
static int fieldName = 6;
static int original = 7;
static int processValue = 8;
private final FieldInfo[] getters;
private final String className;
private final SerializeBeanInfo beanInfo;
private final boolean writeDirect;
private final boolean nonContext;
private Map variants = new HashMap();
private int variantIndex = 9;
public Context(FieldInfo[] getters, //
SerializeBeanInfo beanInfo, //
String className, //
boolean writeDirect, //
boolean nonContext) {
this.getters = getters;
this.className = className;
this.beanInfo = beanInfo;
this.writeDirect = writeDirect;
this.nonContext = nonContext || beanInfo.beanType.isEnum();
}
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 int getFieldOrinal(String name) {
int fieldIndex = -1;
for (int i = 0, size = getters.length; i < size; ++i) {
FieldInfo item = getters[i];
if (item.name.equals(name)) {
fieldIndex = i;
break;
}
}
return fieldIndex;
}
}
}