shade.com.alibaba.fastjson2.writer.ObjectWriterCreatorASM Maven / Gradle / Ivy
package com.alibaba.fastjson2.writer;
import com.alibaba.fastjson2.*;
import com.alibaba.fastjson2.codec.BeanInfo;
import com.alibaba.fastjson2.codec.FieldInfo;
import com.alibaba.fastjson2.internal.asm.*;
import com.alibaba.fastjson2.modules.ObjectWriterModule;
import com.alibaba.fastjson2.util.*;
import java.io.Serializable;
import java.lang.reflect.*;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.time.LocalDate;
import java.time.OffsetDateTime;
import java.util.*;
import java.util.concurrent.atomic.AtomicIntegerArray;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicLongArray;
import java.util.function.Function;
import static com.alibaba.fastjson2.JSONWriter.Feature.*;
import static com.alibaba.fastjson2.internal.asm.ASMUtils.*;
import static com.alibaba.fastjson2.util.JDKUtils.*;
import static com.alibaba.fastjson2.util.TypeUtils.isFunction;
import static com.alibaba.fastjson2.writer.ObjectWriterProvider.TYPE_INT64_MASK;
public class ObjectWriterCreatorASM
extends ObjectWriterCreator {
// GraalVM not support
// Android not support
public static final ObjectWriterCreatorASM INSTANCE = new ObjectWriterCreatorASM(
DynamicClassLoader.getInstance()
);
protected static final AtomicLong seed = new AtomicLong();
protected final DynamicClassLoader classLoader;
static final String[] INTERFACES = {TYPE_OBJECT_WRITER};
static final String METHOD_DESC_WRITE_VALUE = "(" + DESC_JSON_WRITER + "Ljava/lang/Object;)V";
static final String METHOD_DESC_WRITE = "(" + DESC_JSON_WRITER + "Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/reflect/Type;J)V";
static final String METHOD_DESC_WRITE_FIELD_NAME = "(" + DESC_JSON_WRITER + ")V";
static final String METHOD_DESC_WRITE_OBJECT = "(" + DESC_JSON_WRITER + "Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/reflect/Type;J)V";
static final String METHOD_DESC_WRITE_J = "(" + DESC_JSON_WRITER + "J)V";
static final String METHOD_DESC_WRITE_D = "(" + DESC_JSON_WRITER + "D)V";
static final String METHOD_DESC_WRITE_F = "(" + DESC_JSON_WRITER + "F)V";
static final String METHOD_DESC_WRITE_DATE_WITH_FIELD_NAME = "(" + DESC_JSON_WRITER + "ZLjava/util/Date;)V";
static final String METHOD_DESC_WRITE_Z = "(" + DESC_JSON_WRITER + "Z)V";
static final String METHOD_DESC_WRITE_ZARRAY = "(" + DESC_JSON_WRITER + "[Z)V";
static final String METHOD_DESC_WRITE_FARRAY = "(" + DESC_JSON_WRITER + "[F)V";
static final String METHOD_DESC_WRITE_DARRAY = "(" + DESC_JSON_WRITER + "[D)V";
static final String METHOD_DESC_WRITE_I = "(" + DESC_JSON_WRITER + "I)V";
static final String METHOD_DESC_WRITE_SArray = "(" + DESC_JSON_WRITER + "[S)V";
static final String METHOD_DESC_WRITE_BArray = "(" + DESC_JSON_WRITER + "[B)V";
static final String METHOD_DESC_WRITE_CArray = "(" + DESC_JSON_WRITER + "[C)V";
static final String METHOD_DESC_WRITE_ENUM = "(" + DESC_JSON_WRITER + "Ljava/lang/Enum;)V";
static final String METHOD_DESC_WRITE_LIST = "(" + DESC_JSON_WRITER + "Ljava/util/List;)V";
static final String METHOD_DESC_FIELD_WRITE_OBJECT = "(" + DESC_JSON_WRITER + "Ljava/lang/Object;)Z";
static final String METHOD_DESC_GET_OBJECT_WRITER = "(" + DESC_JSON_WRITER + "Ljava/lang/Class;)" + DESC_OBJECT_WRITER;
static final String METHOD_DESC_GET_ITEM_WRITER = "(" + DESC_JSON_WRITER + "Ljava/lang/reflect/Type;)" + DESC_OBJECT_WRITER;
static final String METHOD_DESC_WRITE_TYPE_INFO = "(" + DESC_JSON_WRITER + ")Z";
static final String METHOD_DESC_HAS_FILTER = "(" + DESC_JSON_WRITER + ")Z";
static final String METHOD_DESC_SET_PATH2 = "(" + DESC_FIELD_WRITER + "Ljava/lang/Object;)Ljava/lang/String;";
static final String METHOD_DESC_WRITE_REFERENCE = "(Ljava/lang/String;)V";
static final String METHOD_DESC_WRITE_CLASS_INFO = "(" + DESC_JSON_WRITER + ")V";
static final int THIS = 0;
static final int JSON_WRITER = 1;
static final String NOT_WRITE_DEFAULT_VALUE = "WRITE_DEFAULT_VALUE";
static final String WRITE_NULLS = "WRITE_NULLS";
static final String CONTEXT_FEATURES = "CONTEXT_FEATURES";
static final String UTF8_DIRECT = "UTF8_DIRECT";
static String fieldWriter(int i) {
switch (i) {
case 0:
return "fieldWriter0";
case 1:
return "fieldWriter1";
case 2:
return "fieldWriter2";
case 3:
return "fieldWriter3";
case 4:
return "fieldWriter4";
case 5:
return "fieldWriter5";
case 6:
return "fieldWriter6";
case 7:
return "fieldWriter7";
case 8:
return "fieldWriter8";
case 9:
return "fieldWriter9";
case 10:
return "fieldWriter10";
case 11:
return "fieldWriter11";
case 12:
return "fieldWriter12";
case 13:
return "fieldWriter13";
case 14:
return "fieldWriter14";
case 15:
return "fieldWriter15";
default:
String base = "fieldWriter";
int size = IOUtils.stringSize(i);
char[] chars = new char[base.length() + size];
base.getChars(0, base.length(), chars, 0);
IOUtils.getChars(i, chars.length, chars);
return new String(chars);
}
}
public ObjectWriterCreatorASM() {
this.classLoader = new DynamicClassLoader();
}
public ObjectWriterCreatorASM(ClassLoader classLoader) {
this.classLoader = classLoader instanceof DynamicClassLoader
? (DynamicClassLoader) classLoader
: new DynamicClassLoader(classLoader);
}
@Override
public ObjectWriter createObjectWriter(
List fieldWriters
) {
boolean allFunction = true;
for (int i = 0; i < fieldWriters.size(); i++) {
if (fieldWriters.get(i).getFunction() == null) {
allFunction = false;
break;
}
}
if (!allFunction) {
return super.createObjectWriter(fieldWriters);
}
BeanInfo beanInfo = new BeanInfo();
return jitWriter(null, JSONFactory.getDefaultObjectWriterProvider(), beanInfo, fieldWriters, 0);
}
@Override
public ObjectWriter createObjectWriter(
Class objectClass,
long features,
ObjectWriterProvider provider
) {
int modifiers = objectClass.getModifiers();
boolean externalClass = classLoader.isExternalClass(objectClass);
boolean publicClass = Modifier.isPublic(modifiers);
BeanInfo beanInfo = new BeanInfo();
provider.getBeanInfo(beanInfo, objectClass);
if (beanInfo.serializer != null && ObjectWriter.class.isAssignableFrom(beanInfo.serializer)) {
try {
Constructor constructor = beanInfo.serializer.getDeclaredConstructor();
constructor.setAccessible(true);
return (ObjectWriter) constructor.newInstance();
} catch (InstantiationException | IllegalAccessException | NoSuchMethodException |
InvocationTargetException e) {
throw new JSONException("create serializer error", e);
}
}
long beanFeatures = beanInfo.writerFeatures;
if (beanInfo.seeAlso != null) {
beanFeatures &= ~JSONWriter.Feature.WriteClassName.mask;
}
long writerFieldFeatures = features | beanFeatures;
final boolean fieldBased = (writerFieldFeatures & JSONWriter.Feature.FieldBased.mask) != 0 && !objectClass.isInterface();
if (Throwable.class.isAssignableFrom(objectClass)
|| BeanUtils.isExtendedMap(objectClass)
) {
return super.createObjectWriter(objectClass, features, provider);
}
boolean record = BeanUtils.isRecord(objectClass);
List fieldWriters;
Map fieldWriterMap = new LinkedHashMap<>();
if (!fieldBased || record) {
List fieldWriterList = new ArrayList<>();
boolean fieldWritersCreated = false;
for (ObjectWriterModule module : provider.modules) {
if (module.createFieldWriters(this, objectClass, fieldWriterList)) {
fieldWritersCreated = true;
break;
}
}
if (fieldWritersCreated) {
for (FieldWriter fieldWriter : fieldWriterList) {
Method method = fieldWriter.method;
if (method == null) {
return super.createObjectWriter(objectClass, writerFieldFeatures, provider);
}
fieldWriterMap.putIfAbsent(fieldWriter.fieldName, fieldWriter);
}
} else {
final FieldInfo fieldInfo = new FieldInfo();
if (!record) {
BeanUtils.declaredFields(objectClass, field -> {
fieldInfo.init();
fieldInfo.ignore = (field.getModifiers() & Modifier.PUBLIC) == 0 || (field.getModifiers() & Modifier.TRANSIENT) != 0;
FieldWriter fieldWriter = creteFieldWriter(objectClass, writerFieldFeatures, provider, beanInfo, fieldInfo, field);
if (fieldWriter != null) {
FieldWriter origin = fieldWriterMap.putIfAbsent(fieldWriter.fieldName, fieldWriter);
if (origin != null) {
int cmp = origin.compareTo(fieldWriter);
if (cmp > 0) {
fieldWriterMap.put(fieldWriter.fieldName, fieldWriter);
}
}
}
});
}
Class mixIn = provider.getMixIn(objectClass);
BeanUtils.getters(objectClass, mixIn, beanInfo.kotlin, method -> {
fieldInfo.init();
fieldInfo.features |= writerFieldFeatures;
fieldInfo.format = beanInfo.format;
provider.getFieldInfo(beanInfo, fieldInfo, objectClass, method);
if (fieldInfo.ignore) {
return;
}
String fieldName = getFieldName(objectClass, provider, beanInfo, record, fieldInfo, method);
if (beanInfo.orders != null) {
boolean match = false;
for (int i = 0; i < beanInfo.orders.length; i++) {
if (fieldName.equals(beanInfo.orders[i])) {
fieldInfo.ordinal = i;
match = true;
}
}
if (!match) {
if (fieldInfo.ordinal == 0) {
fieldInfo.ordinal = beanInfo.orders.length;
}
}
}
if (beanInfo.includes != null && beanInfo.includes.length > 0) {
boolean match = false;
for (String include : beanInfo.includes) {
if (include.equals(fieldName)) {
match = true;
break;
}
}
if (!match) {
return;
}
}
// skip typeKey field
if ((beanInfo.writerFeatures & WriteClassName.mask) != 0
&& fieldName.equals(beanInfo.typeKey)) {
return;
}
Class> returnType = method.getReturnType();
// skip function
if (isFunction(returnType) || returnType == Void.TYPE) {
return;
}
method.setAccessible(true);
ObjectWriter writeUsingWriter = null;
if (fieldInfo.writeUsing != null) {
try {
Constructor> constructor = fieldInfo.writeUsing.getDeclaredConstructor();
constructor.setAccessible(true);
writeUsingWriter = (ObjectWriter) constructor.newInstance();
} catch (Exception e) {
throw new JSONException("create writeUsing Writer error, method " + method.getName()
+ ", serializer "
+ fieldInfo.writeUsing.getName(), e
);
}
}
if (writeUsingWriter == null && fieldInfo.fieldClassMixIn) {
writeUsingWriter = ObjectWriterBaseModule.VoidObjectWriter.INSTANCE;
}
FieldWriter fieldWriter = null;
boolean jit = (fieldInfo.features & FieldInfo.JIT) != 0;
if (jit) {
try {
fieldWriter = createFieldWriterLambda(
provider,
objectClass,
fieldName,
fieldInfo.ordinal,
fieldInfo.features,
fieldInfo.format,
fieldInfo.label,
method,
writeUsingWriter
);
} catch (Throwable e) {
jitErrorCount.incrementAndGet();
jitErrorLast = e;
}
}
if (fieldWriter == null) {
fieldWriter = createFieldWriter(
provider,
objectClass,
fieldName,
fieldInfo.ordinal,
fieldInfo.features,
fieldInfo.format,
fieldInfo.label,
method,
writeUsingWriter
);
}
FieldWriter origin = fieldWriterMap.putIfAbsent(fieldName, fieldWriter);
if (origin != null && origin.compareTo(fieldWriter) > 0) {
fieldWriterMap.put(fieldName, fieldWriter);
}
});
}
} else {
final FieldInfo fieldInfo = new FieldInfo();
BeanUtils.declaredFields(objectClass, field -> {
fieldInfo.init();
FieldWriter fieldWriter = creteFieldWriter(objectClass, writerFieldFeatures, provider, beanInfo, fieldInfo, field);
if (fieldWriter != null) {
fieldWriterMap.put(fieldWriter.fieldName, fieldWriter);
}
});
}
fieldWriters = new ArrayList<>(fieldWriterMap.values());
handleIgnores(beanInfo, fieldWriters);
if (beanInfo.alphabetic) {
try {
Collections.sort(fieldWriters);
} catch (Exception e) {
StringBuilder msg = new StringBuilder("fieldWriters sort error, objectClass ")
.append(objectClass.getName())
.append(", fields ");
JSONArray array = new JSONArray();
for (FieldWriter fieldWriter : fieldWriters) {
array.add(
JSONObject.of(
"name", fieldWriter.fieldName,
"type", fieldWriter.fieldClass,
"ordinal", fieldWriter.ordinal,
"field", fieldWriter.field,
"method", fieldWriter.method
)
);
}
msg.append(array);
throw new JSONException(msg.toString(), e);
}
}
boolean match = fieldWriters.size() < 100 && !Throwable.class.isAssignableFrom(objectClass);
if (!publicClass || externalClass) {
for (FieldWriter fieldWriter : fieldWriters) {
if (fieldWriter.method != null) {
match = false;
break;
}
}
}
for (FieldWriter fieldWriter : fieldWriters) {
if (fieldWriter.getInitWriter() != null
|| (fieldWriter.features & FieldInfo.VALUE_MASK) != 0
|| (fieldWriter.features & FieldInfo.RAW_VALUE_MASK) != 0
) {
match = false;
break;
}
}
if (objectClass.getSuperclass() == Object.class) {
String simpleName = objectClass.getSimpleName();
if (simpleName.indexOf('$') != -1 && simpleName.contains("$$")) {
match = false;
}
}
long writerFeatures = features | beanInfo.writerFeatures;
if (!match) {
return super.createObjectWriter(objectClass, features, provider);
}
setDefaultValue(fieldWriters, objectClass);
return jitWriter(objectClass, provider, beanInfo, fieldWriters, writerFeatures);
}
private ObjectWriterAdapter jitWriter(
Class objectClass,
ObjectWriterProvider provider,
BeanInfo beanInfo,
List fieldWriters,
long writerFeatures
) {
ClassWriter cw = new ClassWriter(null);
String className = "OWG_" + seed.incrementAndGet() + "_" + fieldWriters.size() + (objectClass == null ? "" : ("_" + objectClass.getSimpleName()));
String classNameType;
String classNameFull;
Package pkg = ObjectWriterCreatorASM.class.getPackage();
if (pkg != null) {
String packageName = pkg.getName();
int packageNameLength = packageName.length();
int charsLength = packageNameLength + 1 + className.length();
char[] chars = new char[charsLength];
packageName.getChars(0, packageName.length(), chars, 0);
chars[packageNameLength] = '.';
className.getChars(0, className.length(), chars, packageNameLength + 1);
classNameFull = new String(chars);
chars[packageNameLength] = '/';
for (int i = 0; i < packageNameLength; ++i) {
if (chars[i] == '.') {
chars[i] = '/';
}
}
classNameType = new String(chars);
} else {
classNameType = className;
classNameFull = className;
}
String objectWriterSupper;
switch (fieldWriters.size()) {
case 1:
objectWriterSupper = TYPE_OBJECT_WRITER_1;
break;
case 2:
objectWriterSupper = TYPE_OBJECT_WRITER_2;
break;
case 3:
objectWriterSupper = TYPE_OBJECT_WRITER_3;
break;
case 4:
objectWriterSupper = TYPE_OBJECT_WRITER_4;
break;
case 5:
objectWriterSupper = TYPE_OBJECT_WRITER_5;
break;
case 6:
objectWriterSupper = TYPE_OBJECT_WRITER_6;
break;
case 7:
objectWriterSupper = TYPE_OBJECT_WRITER_7;
break;
case 8:
objectWriterSupper = TYPE_OBJECT_WRITER_8;
break;
case 9:
objectWriterSupper = TYPE_OBJECT_WRITER_9;
break;
case 10:
objectWriterSupper = TYPE_OBJECT_WRITER_10;
break;
case 11:
objectWriterSupper = TYPE_OBJECT_WRITER_11;
break;
case 12:
objectWriterSupper = TYPE_OBJECT_WRITER_12;
break;
default:
objectWriterSupper = TYPE_OBJECT_WRITER_ADAPTER;
break;
}
cw.visit(Opcodes.V1_8,
Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL + Opcodes.ACC_SUPER,
classNameType,
objectWriterSupper,
INTERFACES
);
// // define fieldWriter
genFields(fieldWriters, cw, objectWriterSupper);
// init fieldWriter
genMethodInit(fieldWriters, cw, classNameType, objectWriterSupper);
//
// if (objectWriterSupper == TYPE_OBJECT_WRITER_ADAPTER) {
// genGetFieldReader(
// fieldWriters,
// cw,
// classNameType,
// new ObjectWriterAdapter(objectClass, null, null, features, fieldWriters)
// );
// }
genMethodWriteJSONB(provider, objectClass, fieldWriters, cw, classNameType, writerFeatures);
if ((writerFeatures & JSONWriter.Feature.BeanToArray.mask) != 0) {
genMethodWriteArrayMapping(provider, "write", objectClass, writerFeatures, fieldWriters, cw, classNameType);
} else {
genMethodWrite(provider, objectClass, fieldWriters, cw, classNameType, writerFeatures);
}
genMethodWriteArrayMappingJSONB(provider, objectClass, writerFeatures, fieldWriters, cw, classNameType, writerFeatures);
genMethodWriteArrayMapping(provider, "writeArrayMapping", objectClass, writerFeatures, fieldWriters, cw, classNameType);
byte[] code = cw.toByteArray();
Class> deserClass = classLoader.defineClassPublic(classNameFull, code, 0, code.length);
try {
Constructor> constructor = deserClass.getConstructor(Class.class, String.class, String.class, long.class, List.class);
ObjectWriterAdapter objectWriter = (ObjectWriterAdapter) constructor.newInstance(
objectClass,
beanInfo.typeKey,
beanInfo.typeName,
writerFeatures,
fieldWriters
);
if (beanInfo.serializeFilters != null) {
configSerializeFilters(beanInfo, objectWriter);
}
return objectWriter;
} catch (Throwable e) {
throw new JSONException("create objectWriter error, objectType " + objectClass, e);
}
}
private void genMethodWrite(
ObjectWriterProvider provider,
Class objectType,
List fieldWriters,
ClassWriter cw,
String classNameType,
long objectFeatures
) {
MethodWriter mw = cw.visitMethod(
Opcodes.ACC_PUBLIC,
"write",
METHOD_DESC_WRITE,
fieldWriters.size() < 6 ? 512 : 1024
);
final int OBJECT = 2;
final int FIELD_NAME = 3;
final int FIELD_TYPE = 4;
final int FIELD_FEATURES = 5;
final int COMMA = 7;
Label json_ = new Label(), jsonb_ = new Label(), notSuper_ = new Label();
MethodWriterContext mwc = new MethodWriterContext(provider, objectType, objectFeatures, classNameType, mw, 8, false);
mwc.genVariantsMethodBefore(false);
mwc.genIsEnabled(JSONWriter.Feature.IgnoreErrorGetter.mask, notSuper_);
mw.visitVarInsn(Opcodes.ALOAD, THIS);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, OBJECT);
mw.visitVarInsn(Opcodes.ALOAD, FIELD_NAME);
mw.visitVarInsn(Opcodes.ALOAD, FIELD_TYPE);
mw.visitVarInsn(Opcodes.LLOAD, FIELD_FEATURES);
mw.visitMethodInsn(Opcodes.INVOKESPECIAL, TYPE_OBJECT_WRITER_ADAPTER, "write", METHOD_DESC_WRITE_OBJECT, false);
mw.visitInsn(Opcodes.RETURN);
mw.visitLabel(notSuper_);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitFieldInsn(Opcodes.GETFIELD, TYPE_JSON_WRITER, "jsonb", "Z");
mw.visitJumpInsn(Opcodes.IFEQ, json_);
mwc.genIsEnabled(JSONWriter.Feature.BeanToArray.mask, jsonb_);
mw.visitVarInsn(Opcodes.ALOAD, THIS);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, OBJECT);
mw.visitVarInsn(Opcodes.ALOAD, FIELD_NAME);
mw.visitVarInsn(Opcodes.ALOAD, FIELD_TYPE);
mw.visitVarInsn(Opcodes.LLOAD, FIELD_FEATURES);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, classNameType, "writeArrayMappingJSONB", METHOD_DESC_WRITE_OBJECT, false);
mw.visitInsn(Opcodes.RETURN);
mw.visitLabel(jsonb_);
mw.visitVarInsn(Opcodes.ALOAD, THIS);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, OBJECT);
mw.visitVarInsn(Opcodes.ALOAD, FIELD_NAME);
mw.visitVarInsn(Opcodes.ALOAD, FIELD_TYPE);
mw.visitVarInsn(Opcodes.LLOAD, FIELD_FEATURES);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, classNameType, "writeJSONB", METHOD_DESC_WRITE_OBJECT, false);
mw.visitInsn(Opcodes.RETURN);
mw.visitLabel(json_);
Label checkFilter_ = new Label();
mwc.genIsEnabled(JSONWriter.Feature.BeanToArray.mask, checkFilter_);
mw.visitVarInsn(Opcodes.ALOAD, THIS);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, OBJECT);
mw.visitVarInsn(Opcodes.ALOAD, FIELD_NAME);
mw.visitVarInsn(Opcodes.ALOAD, FIELD_TYPE);
mw.visitVarInsn(Opcodes.LLOAD, FIELD_FEATURES);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, classNameType, "writeArrayMapping", METHOD_DESC_WRITE_OBJECT, false);
mw.visitInsn(Opcodes.RETURN);
mw.visitLabel(checkFilter_);
Label object_ = new Label();
mw.visitVarInsn(Opcodes.ALOAD, THIS);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitMethodInsn(Opcodes.INVOKEINTERFACE, TYPE_OBJECT_WRITER, "hasFilter", METHOD_DESC_HAS_FILTER, true);
mw.visitJumpInsn(Opcodes.IFEQ, object_);
mw.visitVarInsn(Opcodes.ALOAD, THIS);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, OBJECT);
mw.visitVarInsn(Opcodes.ALOAD, FIELD_NAME);
mw.visitVarInsn(Opcodes.ALOAD, FIELD_TYPE);
mw.visitVarInsn(Opcodes.LLOAD, FIELD_FEATURES);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, classNameType, "writeWithFilter", METHOD_DESC_WRITE_OBJECT, false);
mw.visitInsn(Opcodes.RETURN);
mw.visitLabel(object_);
Label return_ = new Label();
if (objectType == null || !java.io.Serializable.class.isAssignableFrom(objectType)) {
Label endIgnoreNoneSerializable_ = new Label();
mwc.genIsEnabled(JSONWriter.Feature.IgnoreNoneSerializable.mask, endIgnoreNoneSerializable_);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "writeNull", "()V", false);
mw.visitJumpInsn(Opcodes.GOTO, return_);
mw.visitLabel(endIgnoreNoneSerializable_);
Label endErrorOnNoneSerializable_ = new Label();
mwc.genIsEnabled(JSONWriter.Feature.ErrorOnNoneSerializable.mask, endErrorOnNoneSerializable_);
mw.visitVarInsn(Opcodes.ALOAD, THIS);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, mwc.classNameType, "errorOnNoneSerializable", "()V", false);
mw.visitJumpInsn(Opcodes.GOTO, return_);
mw.visitLabel(endErrorOnNoneSerializable_);
}
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "startObject", "()V", false);
mw.visitInsn(Opcodes.ICONST_1);
mw.visitVarInsn(Opcodes.ISTORE, COMMA); // comma = false
Label writeFields_ = new Label();
isWriteTypeInfo(objectFeatures, mw, OBJECT, FIELD_TYPE, FIELD_FEATURES, writeFields_);
mw.visitVarInsn(Opcodes.ALOAD, THIS);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitMethodInsn(Opcodes.INVOKEINTERFACE, TYPE_OBJECT_WRITER, "writeTypeInfo", METHOD_DESC_WRITE_TYPE_INFO, true);
mw.visitInsn(Opcodes.ICONST_1);
mw.visitInsn(Opcodes.IXOR);
mw.visitVarInsn(Opcodes.ISTORE, COMMA);
mw.visitLabel(writeFields_);
for (int i = 0; i < fieldWriters.size(); i++) {
FieldWriter fieldWriter = fieldWriters.get(i);
gwFieldValue(mwc, fieldWriter, OBJECT, i);
}
mw.visitVarInsn(Opcodes.ALOAD, 1);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "endObject", "()V", false);
mw.visitLabel(return_);
mw.visitInsn(Opcodes.RETURN);
mw.visitMaxs(mwc.maxVariant + 1, mwc.maxVariant + 1);
}
private static void isWriteTypeInfo(
long objectFeatures,
MethodWriter mw,
int OBJECT,
int FIELD_TYPE,
int FEILD_FEATURE,
Label notWriteType
) {
if ((objectFeatures & JSONWriter.Feature.WriteClassName.mask) == 0) {
mw.visitVarInsn(Opcodes.ALOAD, OBJECT);
mw.visitJumpInsn(Opcodes.IFNULL, notWriteType);
mw.visitVarInsn(Opcodes.ALOAD, OBJECT);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;", false);
mw.visitVarInsn(Opcodes.ALOAD, FIELD_TYPE);
mw.visitJumpInsn(Opcodes.IF_ACMPEQ, notWriteType);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, OBJECT);
mw.visitVarInsn(Opcodes.ALOAD, FIELD_TYPE);
mw.visitVarInsn(Opcodes.LLOAD, FEILD_FEATURE);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "isWriteTypeInfo", "(Ljava/lang/Object;Ljava/lang/reflect/Type;J)Z", false);
mw.visitJumpInsn(Opcodes.IFEQ, notWriteType);
}
}
private void genMethodWriteJSONB(
ObjectWriterProvider provider,
Class objectType,
List fieldWriters,
ClassWriter cw,
String classNameType,
long objectFeatures
) {
MethodWriter mw = cw.visitMethod(
Opcodes.ACC_PUBLIC,
"writeJSONB",
METHOD_DESC_WRITE,
fieldWriters.size() < 6 ? 512 : 1024
);
final int OBJECT = 2;
final int FIELD_NAME = 3;
final int FIELD_TYPE = 4;
final int FIELD_FEATURES = 5;
MethodWriterContext mwc = new MethodWriterContext(provider, objectType, objectFeatures, classNameType, mw, 7, true);
mwc.genVariantsMethodBefore(true);
Label return_ = new Label();
if (objectType == null || !java.io.Serializable.class.isAssignableFrom(objectType)) {
Label endIgnoreNoneSerializable_ = new Label();
mwc.genIsEnabled(JSONWriter.Feature.IgnoreNoneSerializable.mask, endIgnoreNoneSerializable_);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "writeNull", "()V", false);
mw.visitJumpInsn(Opcodes.GOTO, return_);
mw.visitLabel(endIgnoreNoneSerializable_);
Label endErrorOnNoneSerializable_ = new Label();
mwc.genIsEnabled(JSONWriter.Feature.ErrorOnNoneSerializable.mask, endErrorOnNoneSerializable_);
mw.visitVarInsn(Opcodes.ALOAD, THIS);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, mwc.classNameType, "errorOnNoneSerializable", "()V", false);
mw.visitJumpInsn(Opcodes.GOTO, return_);
mw.visitLabel(endErrorOnNoneSerializable_);
}
Label notWriteType = new Label();
isWriteTypeInfo(objectFeatures, mw, OBJECT, FIELD_TYPE, FIELD_FEATURES, notWriteType);
mw.visitVarInsn(Opcodes.ALOAD, THIS);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, classNameType, "writeClassInfo", METHOD_DESC_WRITE_CLASS_INFO, false);
mw.visitLabel(notWriteType);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "startObject", "()V", false);
for (int i = 0; i < fieldWriters.size(); i++) {
FieldWriter fieldWriter = fieldWriters.get(i);
gwFieldValueJSONB(mwc, fieldWriter, OBJECT, i);
}
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "endObject", "()V", false);
mw.visitLabel(return_);
mw.visitInsn(Opcodes.RETURN);
mw.visitMaxs(mwc.maxVariant + 1, mwc.maxVariant + 1);
}
private void genMethodWriteArrayMappingJSONB(
ObjectWriterProvider provider,
Class objectType,
long objectFeatures,
List fieldWriters,
ClassWriter cw,
String classNameType,
long features
) {
MethodWriter mw = cw.visitMethod(
Opcodes.ACC_PUBLIC,
"writeArrayMappingJSONB",
METHOD_DESC_WRITE,
512
);
final int OBJECT = 2;
final int FIELD_NAME = 3;
final int FIELD_TYPE = 4;
final int FIELD_FEATURES = 5;
{
Label notWriteType = new Label();
isWriteTypeInfo(objectFeatures, mw, OBJECT, FIELD_TYPE, FIELD_FEATURES, notWriteType);
mw.visitVarInsn(Opcodes.ALOAD, THIS);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, classNameType, "writeClassInfo", METHOD_DESC_WRITE_CLASS_INFO, false);
mw.visitLabel(notWriteType);
}
int size = fieldWriters.size();
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
if (size >= 128) {
mw.visitIntInsn(Opcodes.SIPUSH, size);
} else {
mw.visitIntInsn(Opcodes.BIPUSH, size);
}
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "startArray", "(I)V", false);
MethodWriterContext mwc = new MethodWriterContext(provider, objectType, objectFeatures, classNameType, mw, 7, true);
mwc.genVariantsMethodBefore(true);
for (int i = 0; i < size; i++) {
gwValueJSONB(
mwc,
fieldWriters.get(i),
OBJECT,
i,
false
);
}
mw.visitInsn(Opcodes.RETURN);
mw.visitMaxs(mwc.maxVariant + 1, mwc.maxVariant + 1);
}
private void gwValueJSONB(
MethodWriterContext mwc,
FieldWriter fieldWriter,
int OBJECT,
int i,
boolean table
) {
long features = fieldWriter.features | mwc.objectFeatures;
Class> fieldClass = fieldWriter.fieldClass;
boolean beanToArray = (features & JSONWriter.Feature.BeanToArray.mask) != 0 || table;
boolean userDefineWriter = false;
if ((fieldClass == long.class || fieldClass == Long.class || fieldClass == long[].class)
&& (mwc.provider.userDefineMask & TYPE_INT64_MASK) != 0) {
userDefineWriter = mwc.provider.getObjectWriter(Long.class) != ObjectWriterImplInt64.INSTANCE;
}
if (fieldClass == boolean.class
|| fieldClass == boolean[].class
|| fieldClass == char.class
|| fieldClass == char[].class
|| fieldClass == byte.class
|| fieldClass == byte[].class
|| fieldClass == short.class
|| fieldClass == short[].class
|| fieldClass == int.class
|| fieldClass == int[].class
|| fieldClass == long.class
|| (fieldClass == long[].class && !userDefineWriter)
|| fieldClass == float.class
|| fieldClass == float[].class
|| fieldClass == double.class
|| fieldClass == double[].class
|| fieldClass == String.class
|| fieldClass == Integer.class
|| fieldClass == Long.class
|| fieldClass == BigDecimal.class
|| fieldClass.isEnum()
) {
gwValue(mwc, fieldWriter, OBJECT, i);
} else if (fieldClass == Date.class) {
gwDate(mwc, fieldWriter, OBJECT, i);
} else if (fieldWriter instanceof FieldWriterList) {
gwListJSONB(mwc, fieldWriter, OBJECT, i);
} else if (fieldClass.isArray()) {
gwObjectA(mwc, fieldWriter, OBJECT, i);
} else {
gwObjectJSONB(fieldWriter, OBJECT, mwc, i, beanToArray);
}
}
private void gwObjectJSONB(
FieldWriter fieldWriter,
int OBJECT,
MethodWriterContext mwc,
int i,
boolean beanToArray
) {
Class> fieldClass = fieldWriter.fieldClass;
String fieldName = fieldWriter.fieldName;
String classNameType = mwc.classNameType;
MethodWriter mw = mwc.mw;
int FIELD_VALUE = mwc.var(fieldClass);
int REF_PATH = mwc.var("REF_PATH");
Label endIfNull_ = new Label(), notNull_ = new Label();
genGetObject(mwc, fieldWriter, i, OBJECT);
mw.visitInsn(Opcodes.DUP);
mw.visitVarInsn(Opcodes.ASTORE, FIELD_VALUE);
mw.visitJumpInsn(Opcodes.IFNONNULL, notNull_);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "writeNull", "()V", false);
mw.visitJumpInsn(Opcodes.GOTO, endIfNull_);
mw.visitLabel(notNull_);
boolean refDetection = !ObjectWriterProvider.isNotReferenceDetect(fieldClass);
if (refDetection) {
Label endDetect_ = new Label(), refSetPath_ = new Label();
mwc.genIsEnabled(JSONWriter.Feature.ReferenceDetection.mask, endDetect_);
mw.visitVarInsn(Opcodes.ALOAD, OBJECT);
mw.visitVarInsn(Opcodes.ALOAD, FIELD_VALUE);
mw.visitJumpInsn(Opcodes.IF_ACMPNE, refSetPath_);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitLdcInsn("..");
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "writeReference", "(Ljava/lang/String;)V", false);
mw.visitJumpInsn(Opcodes.GOTO, endIfNull_);
mw.visitLabel(refSetPath_);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, THIS);
mw.visitFieldInsn(Opcodes.GETFIELD, classNameType, fieldWriter(i), DESC_FIELD_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, FIELD_VALUE);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "setPath", METHOD_DESC_SET_PATH2, false);
mw.visitInsn(Opcodes.DUP);
mw.visitVarInsn(Opcodes.ASTORE, REF_PATH);
mw.visitJumpInsn(Opcodes.IFNULL, endDetect_);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, REF_PATH);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "writeReference", METHOD_DESC_WRITE_REFERENCE, false);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, FIELD_VALUE);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "popPath", "(Ljava/lang/Object;)V", false);
mw.visitJumpInsn(Opcodes.GOTO, endIfNull_);
mw.visitLabel(endDetect_);
}
// fw.getObjectWriter(w, value.getClass());
mw.visitVarInsn(Opcodes.ALOAD, THIS);
mw.visitFieldInsn(Opcodes.GETFIELD, classNameType, fieldWriter(i), DESC_FIELD_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, FIELD_VALUE);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;", false);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
TYPE_FIELD_WRITER,
"getObjectWriter",
METHOD_DESC_GET_OBJECT_WRITER,
false);
// objectWriter.write(jw, ctx, value);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, FIELD_VALUE);
mw.visitLdcInsn(fieldName);
mwc.loadFieldType(i, fieldWriter.fieldType);
mw.visitLdcInsn(fieldWriter.features);
mw.visitMethodInsn(
Opcodes.INVOKEINTERFACE,
TYPE_OBJECT_WRITER,
beanToArray ? "writeJSONB" : "writeArrayMappingJSONB",
METHOD_DESC_WRITE_OBJECT,
true
);
if (refDetection) {
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, FIELD_VALUE);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "popPath", "(Ljava/lang/Object;)V", false);
}
mw.visitLabel(endIfNull_);
}
private void gwListJSONB(
MethodWriterContext mwc,
FieldWriter fieldWriter,
int OBJECT,
int i
) {
Type fieldType = fieldWriter.fieldType;
Class> fieldClass = fieldWriter.fieldClass;
String classNameType = mwc.classNameType;
MethodWriter mw = mwc.mw;
int LIST = mwc.var(fieldClass);
int REF_PATH = mwc.var("REF_PATH");
boolean listSimple = false;
Type itemType = null;
Class itemClass = null;
if (fieldType instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) fieldType;
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
if (actualTypeArguments.length == 1) {
itemType = actualTypeArguments[0];
itemClass = TypeUtils.getClass(itemType);
listSimple = (itemType == String.class || itemType == Integer.class || itemType == Long.class);
}
}
Label endIfListNull_ = new Label(), listNotNull_ = new Label();
genGetObject(mwc, fieldWriter, i, OBJECT);
mw.visitInsn(Opcodes.DUP);
mw.visitVarInsn(Opcodes.ASTORE, LIST);
mw.visitJumpInsn(Opcodes.IFNONNULL, listNotNull_);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "writeNull", "()V", false);
mw.visitJumpInsn(Opcodes.GOTO, endIfListNull_);
mw.visitLabel(listNotNull_);
{
Label endDetect_ = new Label(), refSetPath_ = new Label();
mwc.genIsEnabled(JSONWriter.Feature.ReferenceDetection.mask, endDetect_);
mw.visitVarInsn(Opcodes.ALOAD, OBJECT);
mw.visitVarInsn(Opcodes.ALOAD, LIST);
mw.visitJumpInsn(Opcodes.IF_ACMPNE, refSetPath_);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitLdcInsn("..");
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "writeReference", "(Ljava/lang/String;)V", false);
mw.visitJumpInsn(Opcodes.GOTO, endIfListNull_);
mw.visitLabel(refSetPath_);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, THIS);
mw.visitFieldInsn(Opcodes.GETFIELD, classNameType, fieldWriter(i), DESC_FIELD_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, LIST);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "setPath", METHOD_DESC_SET_PATH2, false);
mw.visitInsn(Opcodes.DUP);
mw.visitVarInsn(Opcodes.ASTORE, REF_PATH);
mw.visitJumpInsn(Opcodes.IFNULL, endDetect_);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, REF_PATH);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "writeReference", METHOD_DESC_WRITE_REFERENCE, false);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, LIST);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "popPath", "(Ljava/lang/Object;)V", false);
mw.visitJumpInsn(Opcodes.GOTO, endIfListNull_);
mw.visitLabel(endDetect_);
}
if (listSimple) {
gwListSimpleType(mwc, i, mw, fieldClass, itemClass, LIST);
} else {
int PREVIOUS_CLASS = mwc.var("ITEM_CLASS");
int ITEM_OBJECT_WRITER = mwc.var("ITEM_OBJECT_WRITER");
mw.visitInsn(Opcodes.ACONST_NULL);
mw.visitInsn(Opcodes.DUP);
mw.visitVarInsn(Opcodes.ASTORE, PREVIOUS_CLASS);
mw.visitVarInsn(Opcodes.ASTORE, ITEM_OBJECT_WRITER);
// TODO writeTypeInfo
mw.visitVarInsn(Opcodes.ALOAD, THIS);
mw.visitFieldInsn(Opcodes.GETFIELD, classNameType, fieldWriter(i), DESC_FIELD_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, LIST);
mw.visitMethodInsn(
Opcodes.INVOKEVIRTUAL,
TYPE_FIELD_WRITER,
"writeListValueJSONB",
METHOD_DESC_WRITE_LIST,
false
);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, LIST);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "popPath", "(Ljava/lang/Object;)V", false);
}
mw.visitLabel(endIfListNull_);
}
private void gwDate(MethodWriterContext mwc, FieldWriter fieldWriter, int OBJECT, int i) {
MethodWriter mw = mwc.mw;
mw.visitVarInsn(Opcodes.ALOAD, THIS);
mw.visitFieldInsn(Opcodes.GETFIELD, mwc.classNameType, fieldWriter(i), DESC_FIELD_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitInsn(Opcodes.ICONST_0);
genGetObject(mwc, fieldWriter, i, OBJECT);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_FIELD_WRITER, "writeDate", METHOD_DESC_WRITE_DATE_WITH_FIELD_NAME, false);
}
private void gwValue(MethodWriterContext mwc, FieldWriter fieldWriter, int OBJECT, int i) {
MethodWriter mw = mwc.mw;
Class fieldClass = fieldWriter.fieldClass;
if (fieldClass == String.class) {
genGetObject(mwc, fieldWriter, i, OBJECT);
mw.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/String");
int FIELD_VALUE = mwc.var("FIELD_VALUE_" + fieldWriter.fieldClass.getName());
mw.visitVarInsn(Opcodes.ASTORE, FIELD_VALUE);
gwString(mwc, false, true, FIELD_VALUE);
return;
}
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
genGetObject(mwc, fieldWriter, i, OBJECT);
if (fieldWriter.decimalFormat != null) {
if (fieldClass == double.class) {
mw.visitVarInsn(Opcodes.ALOAD, THIS);
mw.visitFieldInsn(Opcodes.GETFIELD, mwc.classNameType, fieldWriter(i), DESC_FIELD_WRITER);
mw.visitFieldInsn(Opcodes.GETFIELD, TYPE_FIELD_WRITER, "decimalFormat", "Ljava/text/DecimalFormat;");
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "writeDouble", "(DLjava/text/DecimalFormat;)V", false);
} else if (fieldClass == float.class) {
mw.visitVarInsn(Opcodes.ALOAD, THIS);
mw.visitFieldInsn(Opcodes.GETFIELD, mwc.classNameType, fieldWriter(i), DESC_FIELD_WRITER);
mw.visitFieldInsn(Opcodes.GETFIELD, TYPE_FIELD_WRITER, "decimalFormat", "Ljava/text/DecimalFormat;");
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "writeFloat", "(FLjava/text/DecimalFormat;)V", false);
} else if (fieldClass == BigDecimal.class) {
mw.visitLdcInsn(fieldWriter.features);
mw.visitVarInsn(Opcodes.ALOAD, THIS);
mw.visitFieldInsn(Opcodes.GETFIELD, mwc.classNameType, fieldWriter(i), DESC_FIELD_WRITER);
mw.visitFieldInsn(Opcodes.GETFIELD, TYPE_FIELD_WRITER, "decimalFormat", "Ljava/text/DecimalFormat;");
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "writeDecimal", "(Ljava/math/BigDecimal;JLjava/text/DecimalFormat;)V", false);
} else {
throw new UnsupportedOperationException();
}
return;
}
String methodName, methodDesc;
if (fieldClass == boolean.class) {
methodName = "writeBool";
methodDesc = "(Z)V";
} else if (fieldClass == char.class) {
methodName = "writeChar";
methodDesc = "(C)V";
} else if (fieldClass == byte.class) {
methodName = "writeInt8";
methodDesc = "(B)V";
} else if (fieldClass == short.class) {
methodName = "writeInt16";
methodDesc = "(S)V";
} else if (fieldClass == int.class) {
methodName = "writeInt32";
methodDesc = "(I)V";
} else if (fieldClass == Integer.class) {
methodName = "writeInt32";
methodDesc = "(Ljava/lang/Integer;)V";
} else if (fieldClass == long.class) {
methodName = "writeInt64";
methodDesc = "(J)V";
} else if (fieldClass == Long.class) {
methodName = "writeInt64";
methodDesc = "(Ljava/lang/Long;)V";
} else if (fieldClass == float.class) {
methodName = "writeFloat";
methodDesc = "(F)V";
} else if (fieldClass == double.class) {
methodName = "writeDouble";
methodDesc = "(D)V";
} else if (fieldClass == boolean[].class) {
methodName = "writeBool";
methodDesc = "([Z)V";
} else if (fieldClass == char[].class) {
methodName = "writeString";
methodDesc = "([C)V";
} else if (fieldClass == byte[].class) {
methodName = "writeBinary";
methodDesc = "([B)V";
} else if (fieldClass == short[].class) {
methodName = "writeInt16";
methodDesc = "([S)V";
} else if (fieldClass == int[].class) {
methodName = "writeInt32";
methodDesc = "([I)V";
} else if (fieldClass == long[].class && mwc.provider.getObjectWriter(Long.class) == ObjectWriterImplInt64.INSTANCE) {
methodName = "writeInt64";
methodDesc = "([J)V";
} else if (fieldClass == float[].class) {
methodName = "writeFloat";
methodDesc = "([F)V";
} else if (fieldClass == double[].class) {
methodName = "writeDouble";
methodDesc = "([D)V";
} else if (fieldClass == BigDecimal.class) {
methodName = "writeDecimal";
methodDesc = "(Ljava/math/BigDecimal;JLjava/text/DecimalFormat;)V";
mw.visitLdcInsn(fieldWriter.features);
mw.visitInsn(Opcodes.ACONST_NULL);
} else if (Enum.class.isAssignableFrom(fieldClass)) {
methodName = "writeEnum";
methodDesc = "(Ljava/lang/Enum;)V";
// } else if (fieldClass == String.class) {
// methodName = "writeString";
// methodDesc = "(Ljava/lang/String;)V";
} else {
throw new UnsupportedOperationException();
}
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, methodName, methodDesc, false);
}
private void gwObjectA(
MethodWriterContext mwc,
FieldWriter fieldWriter,
int OBJECT,
int i
) {
MethodWriter mw = mwc.mw;
if (fieldWriter.fieldClass == String[].class) {
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
genGetObject(mwc, fieldWriter, i, OBJECT);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "writeString", "([Ljava/lang/String;)V", false);
} else {
mw.visitVarInsn(Opcodes.ALOAD, THIS);
mw.visitFieldInsn(Opcodes.GETFIELD, mwc.classNameType, fieldWriter(i), DESC_FIELD_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, OBJECT);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_FIELD_WRITER, "writeValue", METHOD_DESC_WRITE_VALUE, false);
}
}
private void genMethodWriteArrayMapping(
ObjectWriterProvider provider,
String methodName,
Class objectType,
long objectFeatures,
List fieldWriters,
ClassWriter cw,
String classNameType
) {
MethodWriter mw = cw.visitMethod(Opcodes.ACC_PUBLIC,
methodName,
METHOD_DESC_WRITE,
512
);
final int OBJECT = 2;
final int FIELD_NAME = 3;
final int FIELD_TYPE = 4;
final int FIELD_FEATURES = 5;
Label jsonb_ = new Label();
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitFieldInsn(Opcodes.GETFIELD, TYPE_JSON_WRITER, "jsonb", "Z");
mw.visitJumpInsn(Opcodes.IFEQ, jsonb_);
mw.visitVarInsn(Opcodes.ALOAD, THIS);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, OBJECT);
mw.visitVarInsn(Opcodes.ALOAD, FIELD_NAME);
mw.visitVarInsn(Opcodes.ALOAD, FIELD_TYPE);
mw.visitVarInsn(Opcodes.LLOAD, FIELD_FEATURES);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, classNameType, "writeArrayMappingJSONB", METHOD_DESC_WRITE_OBJECT, false);
mw.visitInsn(Opcodes.RETURN);
mw.visitLabel(jsonb_);
Label object_ = new Label();
mw.visitVarInsn(Opcodes.ALOAD, THIS);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitMethodInsn(Opcodes.INVOKEINTERFACE, TYPE_OBJECT_WRITER, "hasFilter", METHOD_DESC_HAS_FILTER, true);
mw.visitJumpInsn(Opcodes.IFEQ, object_);
mw.visitVarInsn(Opcodes.ALOAD, THIS);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, OBJECT);
mw.visitVarInsn(Opcodes.ALOAD, FIELD_NAME);
mw.visitVarInsn(Opcodes.ALOAD, FIELD_TYPE);
mw.visitVarInsn(Opcodes.LLOAD, FIELD_FEATURES);
mw.visitMethodInsn(Opcodes.INVOKESPECIAL, TYPE_OBJECT_WRITER_ADAPTER, methodName, METHOD_DESC_WRITE, false);
mw.visitInsn(Opcodes.RETURN);
mw.visitLabel(object_);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "startArray", "()V", false);
MethodWriterContext mwc = new MethodWriterContext(provider, objectType, objectFeatures, classNameType, mw, 7, false);
for (int i = 0; i < fieldWriters.size(); i++) {
if (i != 0) {
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "writeComma", "()V", false);
}
gwFieldValueArrayMapping(
fieldWriters.get(i),
mwc,
OBJECT,
i
);
}
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "endArray", "()V", false);
mw.visitInsn(Opcodes.RETURN);
mw.visitMaxs(mwc.maxVariant + 1, mwc.maxVariant + 1);
}
private void gwFieldValueArrayMapping(
FieldWriter fieldWriter,
MethodWriterContext mwc,
int OBJECT,
int i
) {
Class objectType = mwc.objectClass;
Class> fieldClass = fieldWriter.fieldClass;
final String TYPE_OBJECT = objectType == null ? "java/lang/Object" : ASMUtils.type(objectType);
boolean userDefineWriter = false;
if ((fieldClass == long.class || fieldClass == Long.class || fieldClass == long[].class)
&& (mwc.provider.userDefineMask & TYPE_INT64_MASK) != 0) {
userDefineWriter = mwc.provider.getObjectWriter(Long.class) != ObjectWriterImplInt64.INSTANCE;
}
if (fieldClass == boolean.class
|| fieldClass == boolean[].class
|| fieldClass == char.class
|| fieldClass == char[].class
|| fieldClass == byte.class
|| fieldClass == byte[].class
|| fieldClass == short.class
|| fieldClass == short[].class
|| fieldClass == int.class
|| fieldClass == int[].class
|| fieldClass == long.class
|| (fieldClass == long[].class && !userDefineWriter)
|| fieldClass == float.class
|| fieldClass == float[].class
|| fieldClass == double.class
|| fieldClass == double[].class
|| fieldClass == String.class
|| fieldClass == Integer.class
|| fieldClass == Long.class
|| fieldClass == BigDecimal.class
|| fieldClass.isEnum()
) {
gwValue(mwc, fieldWriter, OBJECT, i);
} else if (fieldClass == Date.class) {
gwDate(mwc, fieldWriter, OBJECT, i);
} else if (fieldWriter instanceof FieldWriterList) {
gwList(mwc, OBJECT, i, fieldWriter);
} else {
gwObject(mwc, OBJECT, i, fieldWriter, TYPE_OBJECT);
}
}
private void gwObject(
MethodWriterContext mwc,
int OBJECT,
int i,
FieldWriter fieldWriter,
String TYPE_OBJECT
) {
Class> fieldClass = fieldWriter.fieldClass;
String fieldName = fieldWriter.fieldName;
MethodWriter mw = mwc.mw;
int FIELD_VALUE = mwc.var(fieldClass);
int REF_PATH = mwc.var("REF_PATH");
Label endIfNull_ = new Label(), notNull_ = new Label();
genGetObject(mwc, fieldWriter, i, OBJECT);
mw.visitInsn(Opcodes.DUP);
mw.visitVarInsn(Opcodes.ASTORE, FIELD_VALUE);
mw.visitJumpInsn(Opcodes.IFNONNULL, notNull_);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "writeNull", "()V", false);
mw.visitJumpInsn(Opcodes.GOTO, endIfNull_);
mw.visitLabel(notNull_);
if (fieldClass == Double.class || fieldClass == Float.class || fieldClass == BigDecimal.class) {
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
if (fieldWriter.decimalFormat != null) {
mw.visitVarInsn(Opcodes.ALOAD, FIELD_VALUE);
if (fieldClass == Double.class) {
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D", false);
mw.visitVarInsn(Opcodes.ALOAD, THIS);
mw.visitFieldInsn(Opcodes.GETFIELD, mwc.classNameType, fieldWriter(i), DESC_FIELD_WRITER);
mw.visitFieldInsn(Opcodes.GETFIELD, TYPE_FIELD_WRITER, "decimalFormat", "Ljava/text/DecimalFormat;");
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "writeDouble", "(DLjava/text/DecimalFormat;)V", false);
} else if (fieldClass == Float.class) {
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F", false);
mw.visitVarInsn(Opcodes.ALOAD, THIS);
mw.visitFieldInsn(Opcodes.GETFIELD, mwc.classNameType, fieldWriter(i), DESC_FIELD_WRITER);
mw.visitFieldInsn(Opcodes.GETFIELD, TYPE_FIELD_WRITER, "decimalFormat", "Ljava/text/DecimalFormat;");
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "writeFloat", "(FLjava/text/DecimalFormat;)V", false);
} else {
long features = fieldWriter.features;
mw.visitLdcInsn(features);
mw.visitVarInsn(Opcodes.ALOAD, THIS);
mw.visitFieldInsn(Opcodes.GETFIELD, mwc.classNameType, fieldWriter(i), DESC_FIELD_WRITER);
mw.visitFieldInsn(Opcodes.GETFIELD, TYPE_FIELD_WRITER, "decimalFormat", "Ljava/text/DecimalFormat;");
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "writeDecimal", "(Ljava/math/BigDecimal;JLjava/text/DecimalFormat;)V", false);
}
} else {
mw.visitVarInsn(Opcodes.ALOAD, FIELD_VALUE);
if (fieldClass == Double.class) {
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D", false);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "writeDouble", "(D)V", false);
} else if (fieldClass == Float.class) {
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F", false);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "writeFloat", "(F)V", false);
} else {
long features = fieldWriter.features;
mw.visitLdcInsn(features);
mw.visitInsn(Opcodes.ACONST_NULL);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "writeDecimal", "(Ljava/math/BigDecimal;JLjava/text/DecimalFormat;)V", false);
}
}
} else {
boolean refDetection = !ObjectWriterProvider.isNotReferenceDetect(fieldClass);
if (refDetection) {
Label endDetect_ = new Label(), refSetPath_ = new Label();
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "isRefDetect", "()Z", false);
mw.visitJumpInsn(Opcodes.IFEQ, endDetect_);
mw.visitVarInsn(Opcodes.ALOAD, OBJECT);
mw.visitVarInsn(Opcodes.ALOAD, FIELD_VALUE);
mw.visitJumpInsn(Opcodes.IF_ACMPNE, refSetPath_);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitLdcInsn("..");
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "writeReference", "(Ljava/lang/String;)V", false);
mw.visitJumpInsn(Opcodes.GOTO, endIfNull_);
mw.visitLabel(refSetPath_);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, THIS);
mw.visitFieldInsn(Opcodes.GETFIELD, mwc.classNameType, fieldWriter(i), DESC_FIELD_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, FIELD_VALUE);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "setPath", METHOD_DESC_SET_PATH2, false);
mw.visitInsn(Opcodes.DUP);
mw.visitVarInsn(Opcodes.ASTORE, REF_PATH);
mw.visitJumpInsn(Opcodes.IFNULL, endDetect_);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, REF_PATH);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "writeReference", METHOD_DESC_WRITE_REFERENCE, false);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, FIELD_VALUE);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "popPath", "(Ljava/lang/Object;)V", false);
mw.visitJumpInsn(Opcodes.GOTO, endIfNull_);
mw.visitLabel(endDetect_);
}
if (fieldClass == String[].class) {
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, FIELD_VALUE);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "writeString", "([Ljava/lang/String;)V", false);
} else {
// fw.getObjectWriter(w, value.getClass());
mw.visitVarInsn(Opcodes.ALOAD, THIS);
mw.visitFieldInsn(Opcodes.GETFIELD, mwc.classNameType, fieldWriter(i), DESC_FIELD_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, FIELD_VALUE);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;", false);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
TYPE_FIELD_WRITER,
"getObjectWriter",
METHOD_DESC_GET_OBJECT_WRITER,
false);
// objectWriter.write(jw, ctx, value);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, FIELD_VALUE);
mw.visitLdcInsn(fieldWriter.fieldName);
mwc.loadFieldType(i, fieldWriter.fieldType);
mw.visitLdcInsn(fieldWriter.features);
mw.visitMethodInsn(Opcodes.INVOKEINTERFACE, TYPE_OBJECT_WRITER, "write", METHOD_DESC_WRITE_OBJECT, true);
}
if (refDetection) {
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, FIELD_VALUE);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "popPath", "(Ljava/lang/Object;)V", false);
}
}
mw.visitLabel(endIfNull_);
}
private void gwList(MethodWriterContext mwc, int OBJECT, int i, FieldWriter fieldWriter) {
Type fieldType = fieldWriter.fieldType;
Class> fieldClass = fieldWriter.fieldClass;
int LIST = mwc.var(fieldClass);
MethodWriter mw = mwc.mw;
boolean listSimple = false;
Type itemType;
Class itemClass = null;
if (fieldType instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) fieldType;
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
if (actualTypeArguments.length == 1) {
itemType = actualTypeArguments[0];
itemClass = TypeUtils.getMapping(itemType);
listSimple = (itemType == String.class || itemType == Integer.class || itemType == Long.class);
}
}
Label endIfListNull_ = new Label(), listNotNull_ = new Label();
genGetObject(mwc, fieldWriter, i, OBJECT);
mw.visitInsn(Opcodes.DUP);
mw.visitVarInsn(Opcodes.ASTORE, LIST);
mw.visitJumpInsn(Opcodes.IFNONNULL, listNotNull_);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "writeNull", "()V", false);
mw.visitJumpInsn(Opcodes.GOTO, endIfListNull_);
mw.visitLabel(listNotNull_);
if (listSimple) {
genGetObject(mwc, fieldWriter, i, OBJECT);
mw.visitVarInsn(Opcodes.ASTORE, LIST);
gwListSimpleType(mwc, i, mw, fieldClass, itemClass, LIST);
} else {
int LIST_SIZE = mwc.var("LIST_SIZE");
int J = mwc.var("J");
int ITEM_CLASS = mwc.var(Class.class);
int PREVIOUS_CLASS = mwc.var("PREVIOUS_CLASS");
int ITEM_OBJECT_WRITER = mwc.var("ITEM_OBJECT_WRITER");
mw.visitInsn(Opcodes.ACONST_NULL);
mw.visitInsn(Opcodes.DUP);
mw.visitVarInsn(Opcodes.ASTORE, PREVIOUS_CLASS);
mw.visitVarInsn(Opcodes.ASTORE, ITEM_OBJECT_WRITER);
// for(int j = 0;
mw.visitVarInsn(Opcodes.ALOAD, LIST);
mw.visitMethodInsn(Opcodes.INVOKEINTERFACE, "java/util/List", "size", "()I", true);
mw.visitVarInsn(Opcodes.ISTORE, LIST_SIZE);
// startArray(int size)
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "startArray", "()V", false);
Label for_start_j_ = new Label(), for_end_j_ = new Label(), for_inc_j_ = new Label(), notFirst_ = new Label();
mw.visitInsn(Opcodes.ICONST_0);
mw.visitVarInsn(Opcodes.ISTORE, J);
mw.visitLabel(for_start_j_);
mw.visitVarInsn(Opcodes.ILOAD, J);
mw.visitVarInsn(Opcodes.ILOAD, LIST_SIZE);
mw.visitJumpInsn(Opcodes.IF_ICMPGE, for_end_j_);
mw.visitVarInsn(Opcodes.ILOAD, J);
mw.visitJumpInsn(Opcodes.IFEQ, notFirst_);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "writeComma", "()V", false);
mw.visitLabel(notFirst_);
int ITEM = mwc.var(itemClass);
Label notNull_ = new Label(), classEQ_ = new Label();
mw.visitVarInsn(Opcodes.ALOAD, LIST);
mw.visitVarInsn(Opcodes.ILOAD, J);
mw.visitMethodInsn(Opcodes.INVOKEINTERFACE, "java/util/List", "get", "(I)Ljava/lang/Object;", true);
mw.visitInsn(Opcodes.DUP);
mw.visitVarInsn(Opcodes.ASTORE, ITEM);
// if(item == null)
mw.visitJumpInsn(Opcodes.IFNONNULL, notNull_);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "writeNull", "()V", false);
mw.visitJumpInsn(Opcodes.GOTO, for_inc_j_);
mw.visitLabel(notNull_);
mw.visitVarInsn(Opcodes.ALOAD, ITEM);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;", false);
mw.visitInsn(Opcodes.DUP);
mw.visitVarInsn(Opcodes.ASTORE, ITEM_CLASS);
// if (itemClass == previousClass) {
mw.visitVarInsn(Opcodes.ALOAD, PREVIOUS_CLASS);
mw.visitJumpInsn(Opcodes.IF_ACMPEQ, classEQ_);
// previousObjectWriter = fw_i.getItemWriter(jsonWriter.getContext(), itemClass);
mw.visitVarInsn(Opcodes.ALOAD, 0);
mw.visitFieldInsn(Opcodes.GETFIELD, mwc.classNameType, fieldWriter(i), DESC_FIELD_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, ITEM_CLASS);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_FIELD_WRITER,
"getItemWriter",
METHOD_DESC_GET_ITEM_WRITER,
false
);
mw.visitVarInsn(Opcodes.ASTORE, ITEM_OBJECT_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, ITEM_CLASS);
mw.visitVarInsn(Opcodes.ASTORE, PREVIOUS_CLASS);
mw.visitLabel(classEQ_);
mw.visitVarInsn(Opcodes.ALOAD, ITEM_OBJECT_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, ITEM);
mw.visitVarInsn(Opcodes.ILOAD, J);
mw.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false);
mwc.loadFieldType(i, fieldType);
mw.visitLdcInsn(fieldWriter.features);
mw.visitMethodInsn(Opcodes.INVOKEINTERFACE, TYPE_OBJECT_WRITER, "write", METHOD_DESC_WRITE_OBJECT, true);
mw.visitLabel(for_inc_j_);
mw.visitIincInsn(J, 1);
mw.visitJumpInsn(Opcodes.GOTO, for_start_j_);
mw.visitLabel(for_end_j_);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "endArray", "()V", false);
}
mw.visitLabel(endIfListNull_);
}
private void gwFieldValue(
MethodWriterContext mwc,
FieldWriter fieldWriter,
int OBJECT,
int i
) {
MethodWriter mw = mwc.mw;
Class> fieldClass = fieldWriter.fieldClass;
if (fieldClass == boolean.class) {
gwFieldValueBooleanV(mwc, fieldWriter, OBJECT, i, false);
} else if (fieldClass == boolean[].class
|| fieldClass == byte[].class
|| fieldClass == char[].class
|| fieldClass == short[].class
|| fieldClass == float[].class
|| fieldClass == double[].class
) {
gwFieldValueArray(mwc, fieldWriter, OBJECT, i);
} else if (fieldClass == char.class
|| fieldClass == byte.class
|| fieldClass == short.class
|| fieldClass == float.class
|| fieldClass == double.class
) {
gwFieldName(mwc, fieldWriter, i);
gwValue(mwc, fieldWriter, OBJECT, i);
} else if (fieldClass == int.class) {
gwFieldValueInt32V(mwc, fieldWriter, OBJECT, i, false);
} else if (fieldClass == int[].class) {
gwFieldValueIntVA(mwc, fieldWriter, OBJECT, i, false);
} else if (fieldClass == long.class) {
gwFieldValueInt64V(mwc, fieldWriter, OBJECT, i, false);
} else if (fieldClass == long[].class
&& mwc.provider.getObjectWriter(Long.class) == ObjectWriterImplInt64.INSTANCE
) {
gwFieldValueInt64VA(mwc, fieldWriter, OBJECT, i, false);
} else if (fieldClass == Integer.class) {
gwInt32(mwc, fieldWriter, OBJECT, i);
} else if (fieldClass == Long.class) {
gwInt64(mwc, fieldWriter, OBJECT, i);
} else if (fieldClass == Float.class) {
gwFloat(mwc, fieldWriter, OBJECT, i);
} else if (fieldClass == Double.class) {
gwDouble(mwc, fieldWriter, OBJECT, i);
} else if (fieldClass == String.class) {
gwFieldValueString(mwc, fieldWriter, OBJECT, i);
} else if (fieldClass.isEnum()
&& BeanUtils.getEnumValueField(fieldClass, mwc.provider) == null
&& !(fieldWriter instanceof FieldWriterObject)
) {
gwFieldValueEnum(mwc, fieldWriter, OBJECT, i);
} else if (fieldClass == Date.class) {
gwFieldValueDate(mwc, fieldWriter, OBJECT, i);
} else if (fieldClass == List.class) {
gwFieldValueList(mwc, fieldWriter, OBJECT, i);
} else {
gwFieldValueObject(mwc, fieldWriter, OBJECT, i);
}
}
private void gwFieldValueEnum(
MethodWriterContext mwc,
FieldWriter fieldWriter,
int OBJECT,
int i
) {
Class> fieldClass = fieldWriter.fieldClass;
MethodWriter mw = mwc.mw;
int FIELD_VALUE = mwc.var(fieldClass);
genGetObject(mwc, fieldWriter, i, OBJECT);
mw.visitInsn(Opcodes.DUP);
mw.visitVarInsn(Opcodes.ASTORE, FIELD_VALUE);
Label null_ = new Label(), notNull_ = new Label();
mw.visitJumpInsn(Opcodes.IFNULL, null_);
// void writeEnum(JSONWriter jw, Enum e)
mw.visitVarInsn(Opcodes.ALOAD, 0);
mw.visitFieldInsn(Opcodes.GETFIELD, mwc.classNameType, fieldWriter(i), DESC_FIELD_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, FIELD_VALUE);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_FIELD_WRITER, "writeEnum", METHOD_DESC_WRITE_ENUM, false);
mw.visitJumpInsn(Opcodes.GOTO, notNull_);
mw.visitLabel(null_);
// if (!jw.isWriteNulls())
mw.visitVarInsn(Opcodes.ILOAD, mwc.var(WRITE_NULLS));
mw.visitJumpInsn(Opcodes.IFEQ, notNull_);
// writeFieldName(w);
gwFieldName(mwc, fieldWriter, i);
// jw.writeNulll
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "writeNull", "()V", false);
mw.visitLabel(notNull_);
}
private void gwFieldValueObject(
MethodWriterContext mwc,
FieldWriter fieldWriter,
int OBJECT,
int i
) {
Class> fieldClass = fieldWriter.fieldClass;
Type fieldType = fieldWriter.fieldType;
String fieldName = fieldWriter.fieldName;
boolean refDetection = !ObjectWriterProvider.isNotReferenceDetect(fieldClass);
int FIELD_VALUE = mwc.var(fieldClass);
Integer REF_PATH = null;
if (refDetection) {
REF_PATH = mwc.var("REF_PATH");
}
long features = fieldWriter.features | mwc.objectFeatures;
MethodWriter mw = mwc.mw;
Label null_ = new Label(), notNull_ = new Label();
if (fieldWriter.unwrapped()) {
mw.visitVarInsn(Opcodes.ALOAD, THIS);
mw.visitFieldInsn(Opcodes.GETFIELD, mwc.classNameType, fieldWriter(i), DESC_FIELD_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, OBJECT);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_FIELD_WRITER,
"write", METHOD_DESC_FIELD_WRITE_OBJECT, false);
mw.visitInsn(Opcodes.POP);
mw.visitJumpInsn(Opcodes.GOTO, notNull_);
}
genGetObject(mwc, fieldWriter, i, OBJECT);
mw.visitInsn(Opcodes.DUP);
mw.visitVarInsn(Opcodes.ASTORE, FIELD_VALUE);
mw.visitJumpInsn(Opcodes.IFNULL, null_);
if (!Serializable.class.isAssignableFrom(fieldClass) && fieldClass != List.class) {
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
if (!fieldWriter.isFieldClassSerializable()) {
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "isIgnoreNoneSerializable", "()Z", false);
} else {
mw.visitVarInsn(Opcodes.ALOAD, FIELD_VALUE);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "isIgnoreNoneSerializable", "(Ljava/lang/Object;)Z", false);
}
mw.visitJumpInsn(Opcodes.IFNE, notNull_);
}
if (refDetection) {
Label endDetect_ = new Label(), refSetPath_ = new Label();
int REF_DETECT = mwc.var("REF_DETECT");
if (fieldClass == Object.class) {
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, FIELD_VALUE);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "isRefDetect", "(Ljava/lang/Object;)Z", false);
} else {
mwc.genIsEnabled(JSONWriter.Feature.ReferenceDetection.mask, null);
}
mw.visitInsn(Opcodes.DUP);
mw.visitVarInsn(Opcodes.ISTORE, REF_DETECT);
mw.visitJumpInsn(Opcodes.IFEQ, endDetect_);
mw.visitVarInsn(Opcodes.ALOAD, OBJECT);
mw.visitVarInsn(Opcodes.ALOAD, FIELD_VALUE);
mw.visitJumpInsn(Opcodes.IF_ACMPNE, refSetPath_);
gwFieldName(mwc, fieldWriter, i);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitLdcInsn("..");
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "writeReference", "(Ljava/lang/String;)V", false);
mw.visitJumpInsn(Opcodes.GOTO, notNull_);
mw.visitLabel(refSetPath_);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, THIS);
mw.visitFieldInsn(Opcodes.GETFIELD, mwc.classNameType, fieldWriter(i), DESC_FIELD_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, FIELD_VALUE);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "setPath", METHOD_DESC_SET_PATH2, false);
mw.visitInsn(Opcodes.DUP);
mw.visitVarInsn(Opcodes.ASTORE, REF_PATH);
mw.visitJumpInsn(Opcodes.IFNULL, endDetect_);
gwFieldName(mwc, fieldWriter, i);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, REF_PATH);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "writeReference", METHOD_DESC_WRITE_REFERENCE, false);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, FIELD_VALUE);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "popPath", "(Ljava/lang/Object;)V", false);
mw.visitJumpInsn(Opcodes.GOTO, notNull_);
mw.visitLabel(endDetect_);
if ("this$0".equals(fieldName) || "this$1".equals(fieldName) || "this$2".equals(fieldName)) {
mw.visitVarInsn(Opcodes.ILOAD, REF_DETECT);
mw.visitJumpInsn(Opcodes.IFEQ, notNull_);
}
}
if (Object[].class.isAssignableFrom(fieldClass)) {
Label notWriteEmptyArrayEnd_ = new Label();
mwc.genIsEnabled(JSONWriter.Feature.NotWriteEmptyArray.mask, notWriteEmptyArrayEnd_);
mw.visitVarInsn(Opcodes.ALOAD, FIELD_VALUE);
mw.visitTypeInsn(Opcodes.CHECKCAST, "[Ljava/lang/Object;");
mw.visitInsn(Opcodes.ARRAYLENGTH);
mw.visitJumpInsn(Opcodes.IFNE, notWriteEmptyArrayEnd_);
mw.visitJumpInsn(Opcodes.GOTO, notNull_);
mw.visitLabel(notWriteEmptyArrayEnd_);
}
// writeFieldName(w);
gwFieldName(mwc, fieldWriter, i);
if (fieldClass == BigDecimal.class) {
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, FIELD_VALUE);
mw.visitLdcInsn(features);
if (fieldWriter.decimalFormat != null) {
mw.visitVarInsn(Opcodes.ALOAD, THIS);
mw.visitFieldInsn(Opcodes.GETFIELD, mwc.classNameType, fieldWriter(i), DESC_FIELD_WRITER);
mw.visitFieldInsn(Opcodes.GETFIELD, TYPE_FIELD_WRITER, "decimalFormat", "Ljava/text/DecimalFormat;");
} else {
mw.visitInsn(Opcodes.ACONST_NULL);
}
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "writeDecimal", "(Ljava/math/BigDecimal;JLjava/text/DecimalFormat;)V", false);
} else if (fieldClass == BigInteger.class) {
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, FIELD_VALUE);
if (features == 0) {
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "writeBigInt", "(Ljava/math/BigInteger;)V", false);
} else {
mw.visitLdcInsn(features);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "writeBigInt", "(Ljava/math/BigInteger;J)V", false);
}
} else if (fieldClass == UUID.class) {
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, FIELD_VALUE);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "writeUUID", "(Ljava/util/UUID;)V", false);
} else if (fieldClass == LocalDate.class
&& fieldWriter.format == null
&& mwc.provider.getObjectWriter(LocalDate.class) == ObjectWriterImplLocalDate.INSTANCE
) {
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, FIELD_VALUE);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "writeLocalDate", "(Ljava/time/LocalDate;)V", false);
} else if (fieldClass == OffsetDateTime.class
&& fieldWriter.format == null
&& mwc.provider.getObjectWriter(OffsetDateTime.class) == ObjectWriterImplOffsetDateTime.INSTANCE
) {
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, FIELD_VALUE);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "writeOffsetDateTime", "(Ljava/time/OffsetDateTime;)V", false);
} else if (fieldClass == String[].class) {
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, FIELD_VALUE);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "writeString", "([Ljava/lang/String;)V", false);
} else {
// fw.getObjectWriter(w, value.getClass());
mw.visitVarInsn(Opcodes.ALOAD, THIS);
mw.visitFieldInsn(Opcodes.GETFIELD, mwc.classNameType, fieldWriter(i), DESC_FIELD_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, FIELD_VALUE);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;", false);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_FIELD_WRITER,
"getObjectWriter", METHOD_DESC_GET_OBJECT_WRITER, false);
// objectWriter.write(jw, ctx, value);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, FIELD_VALUE);
mw.visitLdcInsn(fieldName);
mwc.loadFieldType(i, fieldType);
mw.visitLdcInsn(features);
mw.visitMethodInsn(
Opcodes.INVOKEINTERFACE,
TYPE_OBJECT_WRITER,
(features & JSONWriter.Feature.BeanToArray.mask) != 0 ? "writeArrayMapping" : "write",
METHOD_DESC_WRITE_OBJECT,
true
);
}
mw.visitJumpInsn(Opcodes.GOTO, notNull_);
if (refDetection) {
int REF_DETECT = mwc.var("REF_DETECT");
Label endDetect_ = new Label();
mw.visitVarInsn(Opcodes.ILOAD, REF_DETECT);
mw.visitJumpInsn(Opcodes.IFEQ, endDetect_);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, FIELD_VALUE);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "popPath", "(Ljava/lang/Object;)V", false);
mw.visitLabel(endDetect_);
}
mw.visitLabel(null_);
// if (!jw.isWriteNulls())
if ((features & JSONWriter.Feature.WriteNulls.mask) == 0) {
long nullFeatures = JSONWriter.Feature.WriteNulls.mask;
if (fieldClass == AtomicLongArray.class
|| fieldClass == AtomicIntegerArray.class
|| Collection.class.isAssignableFrom(fieldClass)
|| fieldClass.isArray()) {
nullFeatures |= WriteNullListAsEmpty.mask;
nullFeatures |= NullAsDefaultValue.mask;
} else if (Number.class.isAssignableFrom(fieldClass)) {
nullFeatures |= WriteNullNumberAsZero.mask;
nullFeatures |= NullAsDefaultValue.mask;
} else if (fieldClass == Boolean.class) {
nullFeatures |= WriteNullBooleanAsFalse.mask;
nullFeatures |= NullAsDefaultValue.mask;
} else if (fieldClass == String.class) {
nullFeatures |= WriteNullStringAsEmpty.mask;
nullFeatures |= NullAsDefaultValue.mask;
}
mwc.genIsEnabled(nullFeatures, notNull_);
// mw.visitVarInsn(Opcodes.ILOAD, mwc.var(WRITE_NULLS));
// mw.visitJumpInsn(Opcodes.IFEQ, notNull_);
}
// writeFieldName(w);
gwFieldName(mwc, fieldWriter, i);
// jw.writeNulll
String WRITE_NULL_METHOD;
if (fieldClass == AtomicLongArray.class
|| fieldClass == AtomicIntegerArray.class
|| Collection.class.isAssignableFrom(fieldClass)
|| fieldClass.isArray()) {
WRITE_NULL_METHOD = "writeArrayNull";
} else if (Number.class.isAssignableFrom(fieldClass)) {
WRITE_NULL_METHOD = "writeNumberNull";
} else if (fieldClass == Boolean.class) {
WRITE_NULL_METHOD = "writeBooleanNull";
} else if (fieldClass == String.class
|| fieldClass == Appendable.class
|| fieldClass == StringBuffer.class
|| fieldClass == StringBuilder.class) {
WRITE_NULL_METHOD = "writeStringNull";
} else {
WRITE_NULL_METHOD = "writeNull";
}
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, WRITE_NULL_METHOD, "()V", false);
mw.visitLabel(notNull_);
}
private void gwFieldValueList(
MethodWriterContext mwc,
FieldWriter fieldWriter,
int OBJECT,
int i
) {
Type fieldType = fieldWriter.fieldType;
Class> fieldClass = fieldWriter.fieldClass;
MethodWriter mw = mwc.mw;
int LIST = mwc.var(fieldClass);
int REF_PATH = mwc.var("REF_PATH");
Class itemClass = null;
boolean listSimple = false;
if (fieldType instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) fieldType;
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
if (actualTypeArguments.length == 1) {
Type arg0 = actualTypeArguments[0];
itemClass = TypeUtils.getClass(arg0);
listSimple = (arg0 == String.class || arg0 == Integer.class || arg0 == Long.class);
}
}
int FIELD_VALUE = mwc.var(fieldClass);
genGetObject(mwc, fieldWriter, i, OBJECT);
mw.visitInsn(Opcodes.DUP);
mw.visitVarInsn(Opcodes.ASTORE, FIELD_VALUE);
Label null_ = new Label(), notNull_ = new Label();
mw.visitJumpInsn(Opcodes.IFNULL, null_);
{
Label endDetect_ = new Label(), refSetPath_ = new Label();
mwc.genIsEnabled(JSONWriter.Feature.ReferenceDetection.mask, endDetect_);
mw.visitVarInsn(Opcodes.ALOAD, OBJECT);
mw.visitVarInsn(Opcodes.ALOAD, LIST);
mw.visitJumpInsn(Opcodes.IF_ACMPNE, refSetPath_);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitLdcInsn("..");
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "writeReference", "(Ljava/lang/String;)V", false);
mw.visitJumpInsn(Opcodes.GOTO, notNull_);
mw.visitLabel(refSetPath_);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, THIS);
mw.visitFieldInsn(Opcodes.GETFIELD, mwc.classNameType, fieldWriter(i), DESC_FIELD_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, LIST);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "setPath", METHOD_DESC_SET_PATH2, false);
mw.visitInsn(Opcodes.DUP);
mw.visitVarInsn(Opcodes.ASTORE, REF_PATH);
mw.visitJumpInsn(Opcodes.IFNULL, endDetect_);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, REF_PATH);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "writeReference", METHOD_DESC_WRITE_REFERENCE, false);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, LIST);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "popPath", "(Ljava/lang/Object;)V", false);
mw.visitJumpInsn(Opcodes.GOTO, notNull_);
mw.visitLabel(endDetect_);
}
{
Label notWriteEmptyArrayEnd_ = new Label();
mwc.genIsEnabled(JSONWriter.Feature.NotWriteEmptyArray.mask, notWriteEmptyArrayEnd_);
mw.visitVarInsn(Opcodes.ALOAD, LIST);
mw.visitMethodInsn(Opcodes.INVOKEINTERFACE, "java/util/Collection", "isEmpty", "()Z", true);
mw.visitJumpInsn(Opcodes.IFEQ, notWriteEmptyArrayEnd_);
mw.visitJumpInsn(Opcodes.GOTO, notNull_);
mw.visitLabel(notWriteEmptyArrayEnd_);
}
// listStr
if (listSimple) {
// void writeListStr(JSONWriter jw, List list)
// mw.visitVarInsn(Opcodes.ALOAD, THIS);
// mw.visitFieldInsn(Opcodes.GETFIELD, mwc.classNameType, fieldWriter(i), DESC_FIELD_WRITER);
// mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
// mw.visitInsn(Opcodes.ICONST_1);
// mw.visitVarInsn(Opcodes.ALOAD, FIELD_VALUE);
// mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_FIELD_WRITER, "writeListStr", METHOD_DESC_WRITE_LIST, false);
//
gwFieldName(mwc, fieldWriter, i);
gwListSimpleType(mwc, i, mw, fieldClass, itemClass, FIELD_VALUE);
} else {
gwFieldName(mwc, fieldWriter, i);
// void writeList(JSONWriter jw, ObjectWriterContext ctx, List list) {
mw.visitVarInsn(Opcodes.ALOAD, THIS);
mw.visitFieldInsn(Opcodes.GETFIELD, mwc.classNameType, fieldWriter(i), DESC_FIELD_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, FIELD_VALUE);
mw.visitMethodInsn(
Opcodes.INVOKEVIRTUAL,
TYPE_FIELD_WRITER,
mwc.jsonb ? "writeListValueJSONB" : "writeListValue",
METHOD_DESC_WRITE_LIST, false
);
}
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, LIST);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "popPath", "(Ljava/lang/Object;)V", false);
mw.visitJumpInsn(Opcodes.GOTO, notNull_);
mw.visitLabel(null_);
mwc.genIsEnabled(WriteNulls.mask | NullAsDefaultValue.mask | WriteNullListAsEmpty.mask, notNull_);
// writeFieldName(w);
gwFieldName(mwc, fieldWriter, i);
// jw.writeNulll
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "writeArrayNull", "()V", false);
mw.visitLabel(notNull_);
}
private void gwFieldValueJSONB(
MethodWriterContext mwc,
FieldWriter fieldWriter,
int OBJECT,
int i
) {
MethodWriter mw = mwc.mw;
Class objectType = mwc.objectClass;
Class> fieldClass = fieldWriter.fieldClass;
if (fieldClass == boolean.class) {
gwFieldValueBooleanV(mwc, fieldWriter, OBJECT, i, true);
} else if (fieldClass == boolean[].class
|| fieldClass == byte[].class
|| fieldClass == char[].class
|| fieldClass == short[].class
|| fieldClass == float[].class
|| fieldClass == double[].class
) {
gwFieldValueArray(mwc, fieldWriter, OBJECT, i);
} else if (fieldClass == char.class
|| fieldClass == byte.class
|| fieldClass == short.class
|| fieldClass == float.class
|| fieldClass == double.class
) {
gwFieldName(mwc, fieldWriter, i);
gwValue(mwc, fieldWriter, OBJECT, i);
} else if (fieldClass == int.class) {
gwFieldValueInt32V(mwc, fieldWriter, OBJECT, i, true);
} else if (fieldClass == int[].class) {
gwFieldValueIntVA(mwc, fieldWriter, OBJECT, i, true);
} else if (fieldClass == long.class) {
gwFieldValueInt64V(mwc, fieldWriter, OBJECT, i, true);
} else if (fieldClass == long[].class
&& mwc.provider.getObjectWriter(Long.class) == ObjectWriterImplInt64.INSTANCE
) {
gwFieldValueInt64VA(mwc, fieldWriter, OBJECT, i, true);
} else if (fieldClass == Integer.class) {
gwInt32(mwc, fieldWriter, OBJECT, i);
} else if (fieldClass == Long.class) {
gwInt64(mwc, fieldWriter, OBJECT, i);
} else if (fieldClass == String.class) {
gwFieldValueString(mwc, fieldWriter, OBJECT, i);
} else if (fieldClass.isEnum()) {
// gwFieldValueEnumJSONB(classNameType, mw, objectType, OBJECT, i, member, fieldClass, TYPE_OBJECT, true);
gwFieldValueArray(mwc, fieldWriter, OBJECT, i);
} else if (fieldClass == Date.class) {
gwFieldValueDate(mwc, fieldWriter, OBJECT, i);
} else {
gwFieldValueObjectJSONB(mwc, fieldWriter, OBJECT, i);
}
}
private void gwInt32(
MethodWriterContext mwc,
FieldWriter fieldWriter,
int OBJECT,
int i
) {
boolean jsonb = mwc.jsonb;
String classNameType = mwc.classNameType;
MethodWriter mw = mwc.mw;
Class> fieldClass = fieldWriter.fieldClass;
int FIELD_VALUE = mwc.var(fieldClass);
Label endIfNull_ = new Label(), notNull_ = new Label(), writeNullValue_ = new Label();
genGetObject(mwc, fieldWriter, i, OBJECT);
mw.visitInsn(Opcodes.DUP);
mw.visitVarInsn(Opcodes.ASTORE, FIELD_VALUE);
mw.visitJumpInsn(Opcodes.IFNONNULL, notNull_);
if ((fieldWriter.features & (WriteNulls.mask | NullAsDefaultValue.mask | WriteNullNumberAsZero.mask)) == 0) {
mwc.genIsEnabled(
WriteNulls.mask | NullAsDefaultValue.mask | WriteNullNumberAsZero.mask,
writeNullValue_,
endIfNull_
);
mw.visitLabel(writeNullValue_);
gwFieldName(mwc, fieldWriter, i);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "writeNumberNull", "()V", false);
} else {
long features = fieldWriter.features;
if ((features & (WriteNullNumberAsZero.mask | NullAsDefaultValue.mask)) != 0) {
gwFieldName(mwc, fieldWriter, i);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitLdcInsn(0);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "writeInt32", "(I)V", false);
} else { // (features & WriteNulls.mask) != 0
gwFieldName(mwc, fieldWriter, i);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "writeNull", "()V", false);
}
}
mw.visitJumpInsn(Opcodes.GOTO, endIfNull_);
mw.visitLabel(notNull_);
gwFieldName(mwc, fieldWriter, i);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, FIELD_VALUE);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I", false);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "writeInt32", "(I)V", false);
mw.visitLabel(endIfNull_);
}
private void gwInt64(
MethodWriterContext mwc,
FieldWriter fieldWriter,
int OBJECT,
int i
) {
boolean jsonb = mwc.jsonb;
MethodWriter mw = mwc.mw;
Class> fieldClass = fieldWriter.fieldClass;
String classNameType = mwc.classNameType;
int FIELD_VALUE = mwc.var(fieldClass);
Label endIfNull_ = new Label(), notNull_ = new Label(), writeNullValue_ = new Label();
genGetObject(mwc, fieldWriter, i, OBJECT);
mw.visitInsn(Opcodes.DUP);
mw.visitVarInsn(Opcodes.ASTORE, FIELD_VALUE);
mw.visitJumpInsn(Opcodes.IFNONNULL, notNull_);
mwc.genIsEnabled(
WriteNulls.mask | NullAsDefaultValue.mask | WriteNullNumberAsZero.mask,
writeNullValue_,
endIfNull_
);
mw.visitLabel(writeNullValue_);
gwFieldName(mwc, fieldWriter, i);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "writeInt64Null", "()V", false);
mw.visitJumpInsn(Opcodes.GOTO, endIfNull_);
mw.visitLabel(notNull_);
if (jsonb || (fieldWriter.features & (WriteNonStringValueAsString.mask | WriteLongAsString.mask | BrowserCompatible.mask)) == 0) {
gwFieldName(mwc, fieldWriter, i);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, FIELD_VALUE);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J", false);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "writeInt64", "(J)V", false);
} else {
mw.visitVarInsn(Opcodes.ALOAD, THIS);
mw.visitFieldInsn(Opcodes.GETFIELD, classNameType, fieldWriter(i), DESC_FIELD_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, FIELD_VALUE);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J", false);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_FIELD_WRITER, "writeInt64", METHOD_DESC_WRITE_J, false);
}
mw.visitLabel(endIfNull_);
}
private void gwDouble(
MethodWriterContext mwc,
FieldWriter fieldWriter,
int OBJECT,
int i
) {
boolean jsonb = mwc.jsonb;
MethodWriter mw = mwc.mw;
Class> fieldClass = fieldWriter.fieldClass;
String classNameType = mwc.classNameType;
int FIELD_VALUE = mwc.var(fieldClass);
Label endIfNull_ = new Label(), notNull_ = new Label(), writeNullValue_ = new Label();
genGetObject(mwc, fieldWriter, i, OBJECT);
mw.visitInsn(Opcodes.DUP);
mw.visitVarInsn(Opcodes.ASTORE, FIELD_VALUE);
mw.visitJumpInsn(Opcodes.IFNONNULL, notNull_);
mwc.genIsEnabled(
WriteNulls.mask | NullAsDefaultValue.mask | WriteNullNumberAsZero.mask,
writeNullValue_,
endIfNull_
);
mw.visitLabel(writeNullValue_);
gwFieldName(mwc, fieldWriter, i);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "writeNumberNull", "()V", false);
mw.visitJumpInsn(Opcodes.GOTO, endIfNull_);
mw.visitLabel(notNull_);
if (jsonb) {
gwFieldName(mwc, fieldWriter, i);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, FIELD_VALUE);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D", false);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "writeDouble", "(D)V", false);
} else {
mw.visitVarInsn(Opcodes.ALOAD, THIS);
mw.visitFieldInsn(Opcodes.GETFIELD, classNameType, fieldWriter(i), DESC_FIELD_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, FIELD_VALUE);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D", false);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_FIELD_WRITER, "writeDouble", METHOD_DESC_WRITE_D, false);
}
mw.visitLabel(endIfNull_);
}
private void gwFloat(
MethodWriterContext mwc,
FieldWriter fieldWriter,
int OBJECT,
int i
) {
boolean jsonb = mwc.jsonb;
MethodWriter mw = mwc.mw;
Class> fieldClass = fieldWriter.fieldClass;
String classNameType = mwc.classNameType;
int FIELD_VALUE = mwc.var(fieldClass);
Label endIfNull_ = new Label(), notNull_ = new Label(), writeNullValue_ = new Label();
genGetObject(mwc, fieldWriter, i, OBJECT);
mw.visitInsn(Opcodes.DUP);
mw.visitVarInsn(Opcodes.ASTORE, FIELD_VALUE);
mw.visitJumpInsn(Opcodes.IFNONNULL, notNull_);
mwc.genIsEnabled(
WriteNulls.mask | NullAsDefaultValue.mask | WriteNullNumberAsZero.mask,
writeNullValue_,
endIfNull_
);
mw.visitLabel(writeNullValue_);
gwFieldName(mwc, fieldWriter, i);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "writeNumberNull", "()V", false);
mw.visitJumpInsn(Opcodes.GOTO, endIfNull_);
mw.visitLabel(notNull_);
if (jsonb) {
gwFieldName(mwc, fieldWriter, i);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, FIELD_VALUE);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F", false);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "writeFloat", "(D)V", false);
} else {
mw.visitVarInsn(Opcodes.ALOAD, THIS);
mw.visitFieldInsn(Opcodes.GETFIELD, classNameType, fieldWriter(i), DESC_FIELD_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, FIELD_VALUE);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F", false);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_FIELD_WRITER, "writeFloat", METHOD_DESC_WRITE_F, false);
}
mw.visitLabel(endIfNull_);
}
private void gwFieldValueObjectJSONB(
MethodWriterContext mwc,
FieldWriter fieldWriter,
int OBJECT,
int i
) {
MethodWriter mw = mwc.mw;
Class> fieldClass = fieldWriter.fieldClass;
String fieldName = fieldWriter.fieldName;
boolean refDetection = !ObjectWriterProvider.isNotReferenceDetect(fieldClass);
int FIELD_VALUE = mwc.var(fieldClass);
Integer REF_PATH = null;
if (refDetection) {
REF_PATH = mwc.var("REF_PATH");
}
Label endIfNull_ = new Label(), notNull_ = new Label();
genGetObject(mwc, fieldWriter, i, OBJECT);
mw.visitInsn(Opcodes.DUP);
mw.visitVarInsn(Opcodes.ASTORE, FIELD_VALUE);
mw.visitJumpInsn(Opcodes.IFNULL, endIfNull_);
if (!Serializable.class.isAssignableFrom(fieldClass) && fieldClass != List.class) {
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
if (!fieldWriter.isFieldClassSerializable()) {
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "isIgnoreNoneSerializable", "()Z", false);
} else {
mw.visitVarInsn(Opcodes.ALOAD, FIELD_VALUE);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "isIgnoreNoneSerializable", "(Ljava/lang/Object;)Z", false);
}
mw.visitJumpInsn(Opcodes.IFNE, endIfNull_);
}
/**
* boolean refDetect = jsonWriter.isRefDetect();
* if (refDetect) {
* if (value == object) {
* writeFieldName(jsonWriter);
* jsonWriter.writeReference("..");
* goto endIfNull_
* }
*
* String refPath = context.setPath(name, value);
* if (refPath != null) {
* writeFieldName(jsonWriter);
* jsonWriter.writeReference(refPath);
* context.popPath();
* goto endIfNull_
* }
* }
*/
if (refDetection) {
Label endDetect_ = new Label(), refSetPath_ = new Label();
int REF_DETECT = mwc.var("REF_DETECT");
if (fieldClass == Object.class) {
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, FIELD_VALUE);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "isRefDetect", "(Ljava/lang/Object;)Z", false);
} else {
mwc.genIsEnabled(JSONWriter.Feature.ReferenceDetection.mask, null);
}
mw.visitInsn(Opcodes.DUP);
mw.visitVarInsn(Opcodes.ISTORE, REF_DETECT);
mw.visitJumpInsn(Opcodes.IFEQ, endDetect_);
mw.visitVarInsn(Opcodes.ALOAD, OBJECT);
mw.visitVarInsn(Opcodes.ALOAD, FIELD_VALUE);
mw.visitJumpInsn(Opcodes.IF_ACMPNE, refSetPath_);
gwFieldName(mwc, fieldWriter, i);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitLdcInsn("..");
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "writeReference", "(Ljava/lang/String;)V", false);
mw.visitJumpInsn(Opcodes.GOTO, endIfNull_);
mw.visitLabel(refSetPath_);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, THIS);
mw.visitFieldInsn(Opcodes.GETFIELD, mwc.classNameType, fieldWriter(i), DESC_FIELD_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, FIELD_VALUE);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "setPath", METHOD_DESC_SET_PATH2, false);
mw.visitInsn(Opcodes.DUP);
mw.visitVarInsn(Opcodes.ASTORE, REF_PATH);
mw.visitJumpInsn(Opcodes.IFNULL, endDetect_);
gwFieldName(mwc, fieldWriter, i);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, REF_PATH);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "writeReference", METHOD_DESC_WRITE_REFERENCE, false);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, FIELD_VALUE);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "popPath", "(Ljava/lang/Object;)V", false);
mw.visitJumpInsn(Opcodes.GOTO, endIfNull_);
mw.visitLabel(endDetect_);
if ("this$0".equals(fieldName) || "this$1".equals(fieldName) || "this$2".equals(fieldName)) {
mw.visitVarInsn(Opcodes.ILOAD, REF_DETECT);
mw.visitJumpInsn(Opcodes.IFEQ, endIfNull_);
}
}
gwFieldName(mwc, fieldWriter, i);
// fw.getObjectWriter(w, value.getClass());
Class itemClass = fieldWriter.getItemClass();
if (fieldClass == List.class && (itemClass == String.class || itemClass == Integer.class || itemClass == Long.class)) {
gwListSimpleType(mwc, i, mw, fieldClass, itemClass, FIELD_VALUE);
} else {
mw.visitVarInsn(Opcodes.ALOAD, THIS);
mw.visitFieldInsn(Opcodes.GETFIELD, mwc.classNameType, fieldWriter(i), DESC_FIELD_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, FIELD_VALUE);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;", false);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
TYPE_FIELD_WRITER,
"getObjectWriter",
METHOD_DESC_GET_OBJECT_WRITER,
false);
// objectWriter.write(jw, ctx, value);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, FIELD_VALUE);
mw.visitLdcInsn(fieldName);
mwc.loadFieldType(i, fieldWriter.fieldType);
mw.visitLdcInsn(fieldWriter.features);
mw.visitMethodInsn(Opcodes.INVOKEINTERFACE, TYPE_OBJECT_WRITER, "writeJSONB", METHOD_DESC_WRITE_OBJECT, true);
}
if (refDetection) {
int REF_DETECT = mwc.var("REF_DETECT");
Label endDetect_ = new Label();
mw.visitVarInsn(Opcodes.ILOAD, REF_DETECT);
mw.visitJumpInsn(Opcodes.IFEQ, endDetect_);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, FIELD_VALUE);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "popPath", "(Ljava/lang/Object;)V", false);
mw.visitLabel(endDetect_);
}
mw.visitLabel(endIfNull_);
}
private static void gwListSimpleType(
MethodWriterContext mwc,
int i,
MethodWriter mw,
Class> fieldClass,
Class itemClass,
int FIELD_VALUE
) {
if (mwc.jsonb) {
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, FIELD_VALUE);
mwc.loadFieldClass(i, fieldClass);
mw.visitMethodInsn(
Opcodes.INVOKEVIRTUAL,
TYPE_JSON_WRITER,
"checkAndWriteTypeName",
"(Ljava/lang/Object;Ljava/lang/Class;)V",
false
);
}
if (itemClass == Integer.class) {
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, FIELD_VALUE);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "writeListInt32", "(Ljava/util/List;)V", false);
return;
}
if (itemClass == Long.class) {
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, FIELD_VALUE);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "writeListInt64", "(Ljava/util/List;)V", false);
return;
}
if (itemClass == String.class) {
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, FIELD_VALUE);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "writeString", "(Ljava/util/List;)V", false);
return;
}
throw new JSONException("TOOD " + itemClass.getName());
}
static void gwString(MethodWriterContext mwc, boolean symbol, boolean checkNull, int STR) {
MethodWriter mw = mwc.mw;
Label notNull_ = new Label(), endNull_ = new Label();
if (checkNull) {
mw.visitVarInsn(Opcodes.ALOAD, STR);
mw.visitJumpInsn(Opcodes.IFNONNULL, notNull_);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "writeStringNull", "()V", false);
mw.visitJumpInsn(Opcodes.GOTO, endNull_);
mw.visitLabel(notNull_);
}
if (JVM_VERSION == 8
&& !OPENJ9
&& !FIELD_STRING_VALUE_ERROR
&& !symbol
) {
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitFieldInsn(Opcodes.GETSTATIC, ObjectWriterCreatorASMUtils.TYPE_UNSAFE_UTILS, "UNSAFE", "Lsun/misc/Unsafe;");
mw.visitVarInsn(Opcodes.ALOAD, STR);
mw.visitLdcInsn(FIELD_STRING_VALUE_OFFSET);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "sun/misc/Unsafe", "getObject", "(Ljava/lang/Object;J)Ljava/lang/Object;", false);
mw.visitTypeInsn(Opcodes.CHECKCAST, "[C");
mw.visitMethodInsn(
Opcodes.INVOKEVIRTUAL,
TYPE_JSON_WRITER,
"writeString",
"([C)V",
false
);
} else if (JVM_VERSION > 8
&& !OPENJ9
&& FIELD_STRING_CODER_OFFSET != -1
&& FIELD_STRING_VALUE_OFFSET != -1
&& !symbol
) {
Label utf16_ = new Label(), end_ = new Label();
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitFieldInsn(Opcodes.GETSTATIC, ObjectWriterCreatorASMUtils.TYPE_UNSAFE_UTILS, "UNSAFE", "Lsun/misc/Unsafe;");
mw.visitVarInsn(Opcodes.ALOAD, STR);
mw.visitLdcInsn(FIELD_STRING_VALUE_OFFSET);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "sun/misc/Unsafe", "getObject", "(Ljava/lang/Object;J)Ljava/lang/Object;", false);
mw.visitTypeInsn(Opcodes.CHECKCAST, "[B");
mw.visitFieldInsn(Opcodes.GETSTATIC, ObjectWriterCreatorASMUtils.TYPE_UNSAFE_UTILS, "UNSAFE", "Lsun/misc/Unsafe;");
mw.visitVarInsn(Opcodes.ALOAD, STR);
mw.visitLdcInsn(FIELD_STRING_CODER_OFFSET);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "sun/misc/Unsafe", "getByte", "(Ljava/lang/Object;J)B", false);
mw.visitJumpInsn(Opcodes.IFNE, utf16_);
mw.visitMethodInsn(
Opcodes.INVOKEVIRTUAL,
TYPE_JSON_WRITER,
"writeStringLatin1",
"([B)V",
false
);
mw.visitJumpInsn(Opcodes.GOTO, end_);
mw.visitLabel(utf16_);
mw.visitMethodInsn(
Opcodes.INVOKEVIRTUAL,
TYPE_JSON_WRITER,
"writeStringUTF16",
"([B)V",
false
);
mw.visitLabel(end_);
} else {
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, STR);
mw.visitMethodInsn(
Opcodes.INVOKEVIRTUAL,
TYPE_JSON_WRITER,
symbol ? "writeSymbol" : "writeString",
"(Ljava/lang/String;)V",
false
);
}
if (checkNull) {
mw.visitLabel(endNull_);
}
}
private void gwFieldValueDate(
MethodWriterContext mwc,
FieldWriter fieldWriter,
int OBJECT,
int i
) {
MethodWriter mw = mwc.mw;
Class> fieldClass = fieldWriter.fieldClass;
Label null_ = new Label(), writeNull_ = new Label(), endIfNull_ = new Label();
int FIELD_VALUE = mwc.var(fieldClass);
genGetObject(mwc, fieldWriter, i, OBJECT);
mw.visitInsn(Opcodes.DUP);
mw.visitVarInsn(Opcodes.ASTORE, FIELD_VALUE);
mw.visitJumpInsn(Opcodes.IFNULL, null_);
// void writeEnum(JSONWriter jw, Enum e)
mw.visitVarInsn(Opcodes.ALOAD, THIS);
mw.visitFieldInsn(Opcodes.GETFIELD, mwc.classNameType, fieldWriter(i), DESC_FIELD_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, FIELD_VALUE);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/util/Date", "getTime", "()J", false);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_FIELD_WRITER, "writeDate", METHOD_DESC_WRITE_J, false);
mw.visitJumpInsn(Opcodes.GOTO, endIfNull_);
mw.visitLabel(null_);
// if (!jw.isWriteNulls())
if ((fieldWriter.features & WriteNulls.mask) == 0) {
mw.visitVarInsn(Opcodes.ILOAD, mwc.var(WRITE_NULLS));
mw.visitJumpInsn(Opcodes.IFNE, writeNull_);
mw.visitJumpInsn(Opcodes.GOTO, endIfNull_);
}
mw.visitLabel(writeNull_);
gwFieldName(mwc, fieldWriter, i);
// jw.writeNulll
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "writeNull", "()V", false);
mw.visitLabel(endIfNull_);
}
private void gwFieldValueArray(MethodWriterContext mwc, FieldWriter fieldWriter, int OBJECT, int i) {
MethodWriter mw = mwc.mw;
Class fieldClass = fieldWriter.fieldClass;
String methodName, methodDesc;
if (fieldClass == char[].class) {
methodName = "writeString";
methodDesc = METHOD_DESC_WRITE_CArray;
} else if (fieldClass == boolean[].class) {
methodName = "writeBool";
methodDesc = METHOD_DESC_WRITE_ZARRAY;
} else if (fieldClass == byte[].class) {
methodName = "writeBinary";
methodDesc = METHOD_DESC_WRITE_BArray;
} else if (fieldClass == short[].class) {
methodName = "writeInt16";
methodDesc = METHOD_DESC_WRITE_SArray;
} else if (fieldClass == float[].class) {
methodName = "writeFloat";
methodDesc = METHOD_DESC_WRITE_FARRAY;
} else if (fieldClass == double[].class) {
methodName = "writeDouble";
methodDesc = METHOD_DESC_WRITE_DARRAY;
} else if (fieldClass.isEnum()) {
methodName = "writeEnumJSONB";
methodDesc = METHOD_DESC_WRITE_ENUM;
} else {
throw new UnsupportedOperationException();
}
mw.visitVarInsn(Opcodes.ALOAD, THIS);
mw.visitFieldInsn(Opcodes.GETFIELD, mwc.classNameType, fieldWriter(i), DESC_FIELD_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
genGetObject(mwc, fieldWriter, i, OBJECT);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_FIELD_WRITER, methodName, methodDesc, false);
}
private void gwFieldName(MethodWriterContext mwc, FieldWriter fieldWriter, int i) {
MethodWriter mw = mwc.mw;
String classNameType = mwc.classNameType;
Label labelElse = new Label(), labelEnd = new Label();
boolean writeDirect = false;
if (!mwc.jsonb) {
byte[] fieldNameUTF8 = fieldWriter.fieldName.getBytes(StandardCharsets.UTF_8);
int length = fieldNameUTF8.length;
if (length >= 2 && length <= 15) {
writeDirect = true;
Number name1 = 0;
String methodName;
String methodDesc = "(J)V";
byte[] bytes = new byte[8];
switch (length) {
case 2:
bytes[0] = '"';
System.arraycopy(fieldNameUTF8, 0, bytes, 1, 2);
bytes[3] = '"';
bytes[4] = ':';
methodName = "writeName2Raw";
break;
case 3:
bytes[0] = '"';
System.arraycopy(fieldNameUTF8, 0, bytes, 1, 3);
bytes[4] = '"';
bytes[5] = ':';
methodName = "writeName3Raw";
break;
case 4:
bytes[0] = '"';
System.arraycopy(fieldNameUTF8, 0, bytes, 1, 4);
bytes[5] = '"';
bytes[6] = ':';
methodName = "writeName4Raw";
break;
case 5:
bytes[0] = '"';
System.arraycopy(fieldNameUTF8, 0, bytes, 1, 5);
bytes[6] = '"';
bytes[7] = ':';
methodName = "writeName5Raw";
break;
case 6:
bytes[0] = '"';
System.arraycopy(fieldNameUTF8, 0, bytes, 1, 6);
bytes[7] = '"';
methodName = "writeName6Raw";
break;
case 7:
bytes[0] = '"';
System.arraycopy(fieldNameUTF8, 0, bytes, 1, 7);
methodName = "writeName7Raw";
break;
case 8: {
bytes = fieldNameUTF8;
methodName = "writeName8Raw";
break;
}
case 9: {
bytes[0] = '"';
System.arraycopy(fieldNameUTF8, 0, bytes, 1, 7);
methodDesc = "(JI)V";
byte[] name1Bytes = new byte[4];
name1Bytes[0] = fieldNameUTF8[7];
name1Bytes[1] = fieldNameUTF8[8];
name1Bytes[2] = '"';
name1Bytes[3] = ':';
name1 = UNSAFE.getInt(name1Bytes, ARRAY_BYTE_BASE_OFFSET);
methodName = "writeName9Raw";
break;
}
case 10: {
bytes[0] = '"';
System.arraycopy(fieldNameUTF8, 0, bytes, 1, 7);
methodDesc = "(JJ)V";
byte[] name1Bytes = new byte[8];
name1Bytes[0] = fieldNameUTF8[7];
name1Bytes[1] = fieldNameUTF8[8];
name1Bytes[2] = fieldNameUTF8[9];
name1Bytes[3] = '"';
name1Bytes[4] = ':';
name1 = UNSAFE.getLong(name1Bytes, ARRAY_BYTE_BASE_OFFSET);
methodName = "writeName10Raw";
break;
}
case 11: {
bytes[0] = '"';
System.arraycopy(fieldNameUTF8, 0, bytes, 1, 7);
methodDesc = "(JJ)V";
byte[] name1Bytes = new byte[8];
name1Bytes[0] = fieldNameUTF8[7];
name1Bytes[1] = fieldNameUTF8[8];
name1Bytes[2] = fieldNameUTF8[9];
name1Bytes[3] = fieldNameUTF8[10];
name1Bytes[4] = '"';
name1Bytes[5] = ':';
name1 = UNSAFE.getLong(name1Bytes, ARRAY_BYTE_BASE_OFFSET);
methodName = "writeName11Raw";
break;
}
case 12: {
bytes[0] = '"';
System.arraycopy(fieldNameUTF8, 0, bytes, 1, 7);
methodDesc = "(JJ)V";
byte[] name1Bytes = new byte[8];
name1Bytes[0] = fieldNameUTF8[7];
name1Bytes[1] = fieldNameUTF8[8];
name1Bytes[2] = fieldNameUTF8[9];
name1Bytes[3] = fieldNameUTF8[10];
name1Bytes[4] = fieldNameUTF8[11];
name1Bytes[5] = '"';
name1Bytes[6] = ':';
name1 = UNSAFE.getLong(name1Bytes, ARRAY_BYTE_BASE_OFFSET);
methodName = "writeName12Raw";
break;
}
case 13: {
bytes[0] = '"';
System.arraycopy(fieldNameUTF8, 0, bytes, 1, 7);
methodDesc = "(JJ)V";
byte[] name1Bytes = new byte[8];
name1Bytes[0] = fieldNameUTF8[7];
name1Bytes[1] = fieldNameUTF8[8];
name1Bytes[2] = fieldNameUTF8[9];
name1Bytes[3] = fieldNameUTF8[10];
name1Bytes[4] = fieldNameUTF8[11];
name1Bytes[5] = fieldNameUTF8[12];
name1Bytes[6] = '"';
name1Bytes[7] = ':';
name1 = UNSAFE.getLong(name1Bytes, ARRAY_BYTE_BASE_OFFSET);
methodName = "writeName13Raw";
break;
}
case 14: {
bytes[0] = '"';
System.arraycopy(fieldNameUTF8, 0, bytes, 1, 7);
methodDesc = "(JJ)V";
byte[] name1Bytes = new byte[8];
name1Bytes[0] = fieldNameUTF8[7];
name1Bytes[1] = fieldNameUTF8[8];
name1Bytes[2] = fieldNameUTF8[9];
name1Bytes[3] = fieldNameUTF8[10];
name1Bytes[4] = fieldNameUTF8[11];
name1Bytes[5] = fieldNameUTF8[12];
name1Bytes[6] = fieldNameUTF8[13];
name1Bytes[7] = '"';
name1 = UNSAFE.getLong(name1Bytes, ARRAY_BYTE_BASE_OFFSET);
methodName = "writeName14Raw";
break;
}
case 15: {
bytes[0] = '"';
System.arraycopy(fieldNameUTF8, 0, bytes, 1, 7);
methodDesc = "(JJ)V";
name1 = UNSAFE.getLong(fieldNameUTF8, ARRAY_BYTE_BASE_OFFSET + 7);
methodName = "writeName15Raw";
break;
}
default:
throw new IllegalStateException("length : " + length);
}
long nameIn64 = UNSAFE.getLong(bytes, ARRAY_BYTE_BASE_OFFSET);
mw.visitVarInsn(Opcodes.ILOAD, mwc.var(UTF8_DIRECT));
mw.visitJumpInsn(Opcodes.IFEQ, labelElse);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitLdcInsn(nameIn64);
if ("(JI)V".equals(methodDesc)) {
mw.visitLdcInsn(name1.intValue());
} else if ("(JJ)V".equals(methodDesc)) {
mw.visitLdcInsn(name1.longValue());
}
mw.visitMethodInsn(
Opcodes.INVOKEVIRTUAL,
TYPE_JSON_WRITER,
methodName,
methodDesc,
false
);
mw.visitJumpInsn(Opcodes.GOTO, labelEnd);
}
}
if (writeDirect) {
mw.visitLabel(labelElse);
}
mw.visitVarInsn(Opcodes.ALOAD, THIS);
mw.visitFieldInsn(Opcodes.GETFIELD, classNameType, fieldWriter(i), DESC_FIELD_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitMethodInsn(
Opcodes.INVOKEVIRTUAL,
TYPE_FIELD_WRITER,
mwc.jsonb ? "writeFieldNameJSONB" : "writeFieldName",
METHOD_DESC_WRITE_FIELD_NAME,
false
);
if (writeDirect) {
mw.visitLabel(labelEnd);
}
}
private void gwFieldValueInt64VA(
MethodWriterContext mwc,
FieldWriter fieldWriter,
int OBJECT,
int i,
boolean jsonb
) {
MethodWriter mw = mwc.mw;
Class> fieldClass = fieldWriter.fieldClass;
int FIELD_VALUE = mwc.var(fieldClass);
Label endIfNull_ = new Label(), notNull_ = new Label(), writeNullValue_ = new Label();
genGetObject(mwc, fieldWriter, i, OBJECT);
mw.visitInsn(Opcodes.DUP);
mw.visitVarInsn(Opcodes.ASTORE, FIELD_VALUE);
mw.visitJumpInsn(Opcodes.IFNONNULL, notNull_);
mw.visitVarInsn(Opcodes.ILOAD, mwc.var(WRITE_NULLS));
mw.visitJumpInsn(Opcodes.IFNE, writeNullValue_);
mw.visitJumpInsn(Opcodes.GOTO, endIfNull_);
mw.visitLabel(writeNullValue_);
gwFieldName(mwc, fieldWriter, i);
// TODO if ((features & (JSONWriter.Feature.WriteNulls.mask | JSONWriter.Feature.NullAsEmpty.mask)) == 0) {
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "writeArrayNull", "()V", false);
mw.visitJumpInsn(Opcodes.GOTO, endIfNull_);
mw.visitLabel(notNull_);
gwFieldName(mwc, fieldWriter, i);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, FIELD_VALUE);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "writeInt64", "([J)V", false);
mw.visitLabel(endIfNull_);
}
private void gwFieldValueInt64V(
MethodWriterContext mwc,
FieldWriter fieldWriter,
int OBJECT,
int i,
boolean jsonb
) {
MethodWriter mw = mwc.mw;
String format = fieldWriter.format;
String classNameType = mwc.classNameType;
int FIELD_VALUE = mwc.var(long.class);
int WRITE_DEFAULT_VALUE = mwc.var(NOT_WRITE_DEFAULT_VALUE);
Label notDefaultValue_ = new Label(), endWriteValue_ = new Label();
genGetObject(mwc, fieldWriter, i, OBJECT);
mw.visitInsn(Opcodes.DUP2);
mw.visitVarInsn(Opcodes.LSTORE, FIELD_VALUE);
mw.visitInsn(Opcodes.LCONST_0);
mw.visitInsn(Opcodes.LCMP);
mw.visitJumpInsn(Opcodes.IFNE, notDefaultValue_);
if (fieldWriter.defaultValue == null) {
mw.visitVarInsn(Opcodes.ILOAD, WRITE_DEFAULT_VALUE);
mw.visitJumpInsn(Opcodes.IFEQ, notDefaultValue_);
mw.visitJumpInsn(Opcodes.GOTO, endWriteValue_);
}
mw.visitLabel(notDefaultValue_);
boolean iso8601 = "iso8601".equals(format);
if (iso8601 || (fieldWriter.features & (WriteNonStringValueAsString.mask | WriteLongAsString.mask | BrowserCompatible.mask)) != 0) {
mw.visitVarInsn(Opcodes.ALOAD, THIS);
mw.visitFieldInsn(Opcodes.GETFIELD, classNameType, fieldWriter(i), DESC_FIELD_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.LLOAD, FIELD_VALUE);
mw.visitMethodInsn(
Opcodes.INVOKEVIRTUAL,
TYPE_FIELD_WRITER,
iso8601 ? "writeDate" : "writeInt64",
METHOD_DESC_WRITE_J,
false
);
} else {
gwFieldName(mwc, fieldWriter, i);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.LLOAD, FIELD_VALUE);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "writeInt64", "(J)V", false);
}
mw.visitLabel(endWriteValue_);
}
void gwFieldValueIntVA(
MethodWriterContext mwc,
FieldWriter fieldWriter,
int OBJECT,
int i,
boolean jsonb
) {
MethodWriter mw = mwc.mw;
Class> fieldClass = fieldWriter.fieldClass;
int FIELD_VALUE = mwc.var(fieldClass);
Label endIfNull_ = new Label(), notNull_ = new Label(), writeNullValue_ = new Label();
genGetObject(mwc, fieldWriter, i, OBJECT);
mw.visitInsn(Opcodes.DUP);
mw.visitVarInsn(Opcodes.ASTORE, FIELD_VALUE);
mw.visitJumpInsn(Opcodes.IFNONNULL, notNull_);
mw.visitVarInsn(Opcodes.ILOAD, mwc.var(WRITE_NULLS));
mw.visitJumpInsn(Opcodes.IFNE, writeNullValue_);
mw.visitJumpInsn(Opcodes.GOTO, endIfNull_);
mw.visitLabel(writeNullValue_);
gwFieldName(mwc, fieldWriter, i);
// TODO if ((features & (JSONWriter.Feature.WriteNulls.mask | JSONWriter.Feature.NullAsEmpty.mask)) == 0) {
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "writeArrayNull", "()V", false);
mw.visitJumpInsn(Opcodes.GOTO, endIfNull_);
mw.visitLabel(notNull_);
gwFieldName(mwc, fieldWriter, i);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, FIELD_VALUE);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "writeInt32", "([I)V", false);
mw.visitLabel(endIfNull_);
}
private void gwFieldValueInt32V(
MethodWriterContext mwc,
FieldWriter fieldWriter,
int OBJECT,
int i,
boolean jsonb
) {
MethodWriter mw = mwc.mw;
String format = fieldWriter.format;
String classNameType = mwc.classNameType;
int FIELD_VALUE = mwc.var(int.class);
int WRITE_DEFAULT_VALUE = mwc.var(NOT_WRITE_DEFAULT_VALUE);
Label notDefaultValue_ = new Label(), endWriteValue_ = new Label();
genGetObject(mwc, fieldWriter, i, OBJECT);
mw.visitInsn(Opcodes.DUP);
mw.visitVarInsn(Opcodes.ISTORE, FIELD_VALUE);
mw.visitJumpInsn(Opcodes.IFNE, notDefaultValue_);
if (fieldWriter.defaultValue == null) {
mw.visitVarInsn(Opcodes.ILOAD, WRITE_DEFAULT_VALUE);
mw.visitJumpInsn(Opcodes.IFEQ, notDefaultValue_);
mw.visitJumpInsn(Opcodes.GOTO, endWriteValue_);
}
mw.visitLabel(notDefaultValue_);
gwFieldName(mwc, fieldWriter, i);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ILOAD, FIELD_VALUE);
if ("string".equals(format)) {
mw.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Integer", "toString", "(I)Ljava/lang/String;", false);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "writeString", "(Ljava/lang/String;)V", false);
} else if (format != null) {
mw.visitLdcInsn(format);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "writeInt32", "(ILjava/lang/String;)V", false);
} else if (format != null) {
mw.visitFieldInsn(Opcodes.GETFIELD, mwc.classNameType, fieldWriter(i), DESC_FIELD_WRITER);
mw.visitFieldInsn(Opcodes.GETFIELD, TYPE_FIELD_WRITER, "decimalFormat", "Ljava/text/DecimalFormat;");
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "writeInt32", "(ILjava/text/DecimalFormat;)V", false);
} else {
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "writeInt32", "(I)V", false);
}
mw.visitLabel(endWriteValue_);
}
private void gwFieldValueBooleanV(
MethodWriterContext mwc,
FieldWriter fieldWriter,
int OBJECT,
int i,
boolean jsonb
) {
MethodWriter mw = mwc.mw;
String classNameType = mwc.classNameType;
int FIELD_VALUE = mwc.var(boolean.class);
int WRITE_DEFAULT_VALUE = mwc.var(NOT_WRITE_DEFAULT_VALUE);
Label notDefaultValue_ = new Label(), endWriteValue_ = new Label();
genGetObject(mwc, fieldWriter, i, OBJECT);
mw.visitInsn(Opcodes.DUP);
mw.visitVarInsn(Opcodes.ISTORE, FIELD_VALUE);
mw.visitJumpInsn(Opcodes.IFNE, notDefaultValue_);
if (fieldWriter.defaultValue == null) {
mw.visitVarInsn(Opcodes.ILOAD, WRITE_DEFAULT_VALUE);
mw.visitJumpInsn(Opcodes.IFEQ, notDefaultValue_);
mw.visitJumpInsn(Opcodes.GOTO, endWriteValue_);
}
mw.visitLabel(notDefaultValue_);
mw.visitVarInsn(Opcodes.ALOAD, THIS);
mw.visitFieldInsn(Opcodes.GETFIELD, classNameType, fieldWriter(i), DESC_FIELD_WRITER);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitVarInsn(Opcodes.ILOAD, FIELD_VALUE);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_FIELD_WRITER, "writeBool", METHOD_DESC_WRITE_Z, false);
mw.visitLabel(endWriteValue_);
}
private void gwFieldValueString(
MethodWriterContext mwc,
FieldWriter fieldWriter,
int OBJECT,
int i
) {
boolean jsonb = mwc.jsonb;
long features = fieldWriter.features | mwc.objectFeatures;
MethodWriter mw = mwc.mw;
Class> fieldClass = fieldWriter.fieldClass;
String format = fieldWriter.format;
int FIELD_VALUE = mwc.var(fieldClass);
Label null_ = new Label(), endIfNull_ = new Label();
genGetObject(mwc, fieldWriter, i, OBJECT);
mw.visitInsn(Opcodes.DUP);
mw.visitVarInsn(Opcodes.ASTORE, FIELD_VALUE);
mw.visitJumpInsn(Opcodes.IFNULL, null_);
// void writeFieldName(JSONWriter w)
gwFieldName(mwc, fieldWriter, i);
if ("trim".equals(format)) {
mw.visitVarInsn(Opcodes.ALOAD, FIELD_VALUE);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "trim", "()Ljava/lang/String;", false);
mw.visitVarInsn(Opcodes.ASTORE, FIELD_VALUE);
}
final boolean symbol = jsonb && "symbol".equals(format);
gwString(mwc, symbol, false, FIELD_VALUE);
mw.visitJumpInsn(Opcodes.GOTO, endIfNull_);
mw.visitLabel(null_);
Label writeNullValue_ = new Label(), writeNull_ = new Label();
final long defaultValueMask = NullAsDefaultValue.mask
| WriteNullNumberAsZero.mask
| WriteNullBooleanAsFalse.mask
| WriteNullListAsEmpty.mask
| WriteNullStringAsEmpty.mask;
// if (!jw.isWriteNulls())
if ((features & (JSONWriter.Feature.WriteNulls.mask | defaultValueMask)) == 0) {
mwc.genIsEnabled(
WriteNulls.mask | NullAsDefaultValue.mask | WriteNullStringAsEmpty.mask,
writeNull_,
endIfNull_
);
}
mw.visitLabel(writeNull_);
if (fieldWriter.defaultValue == null) {
mwc.genIsDisabled(NotWriteDefaultValue.mask, endIfNull_);
}
// writeFieldName(w);
gwFieldName(mwc, fieldWriter, i);
if ((features & defaultValueMask) == 0) {
long mask = NullAsDefaultValue.mask;
if (fieldClass == String.class) {
mask |= WriteNullStringAsEmpty.mask;
} else if (fieldClass == Boolean.class) {
mask |= WriteNullBooleanAsFalse.mask;
} else if (Number.class.isAssignableFrom(fieldClass)) {
mask |= JSONWriter.Feature.WriteNullNumberAsZero.mask;
} else if (Collection.class.isAssignableFrom(fieldClass)) {
mask |= WriteNullListAsEmpty.mask;
}
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitLdcInsn(mask);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "isEnabled", "(J)Z", false);
mw.visitJumpInsn(Opcodes.IFEQ, writeNullValue_);
}
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitLdcInsn("");
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "writeString", "(Ljava/lang/String;)V", false);
mw.visitJumpInsn(Opcodes.GOTO, endIfNull_);
// jw.writeNulll
mw.visitLabel(writeNullValue_);
mw.visitVarInsn(Opcodes.ALOAD, JSON_WRITER);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_JSON_WRITER, "writeStringNull", "()V", false);
mw.visitLabel(endIfNull_);
}
private void genMethodInit(List fieldWriters,
ClassWriter cw,
String classNameType,
String objectWriterSupper) {
MethodWriter mw = cw.visitMethod(
Opcodes.ACC_PUBLIC,
"",
"(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;JLjava/util/List;)V",
64
);
mw.visitVarInsn(Opcodes.ALOAD, THIS);
mw.visitVarInsn(Opcodes.ALOAD, 1);
mw.visitVarInsn(Opcodes.ALOAD, 2);
mw.visitVarInsn(Opcodes.ALOAD, 3);
mw.visitVarInsn(Opcodes.LLOAD, 4);
mw.visitVarInsn(Opcodes.ALOAD, 6);
mw.visitMethodInsn(Opcodes.INVOKESPECIAL, objectWriterSupper, "", "(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;JLjava/util/List;)V", false);
if (objectWriterSupper == TYPE_OBJECT_WRITER_ADAPTER) {
for (int i = 0; i < fieldWriters.size(); i++) {
mw.visitVarInsn(Opcodes.ALOAD, THIS);
mw.visitInsn(Opcodes.DUP);
mw.visitFieldInsn(Opcodes.GETFIELD, TYPE_OBJECT_WRITER_ADAPTER, "fieldWriterArray", DESC_FIELD_WRITER_ARRAY);
switch (i) {
case 0:
mw.visitInsn(Opcodes.ICONST_0);
break;
case 1:
mw.visitInsn(Opcodes.ICONST_1);
break;
case 2:
mw.visitInsn(Opcodes.ICONST_2);
break;
case 3:
mw.visitInsn(Opcodes.ICONST_3);
break;
case 4:
mw.visitInsn(Opcodes.ICONST_4);
break;
case 5:
mw.visitInsn(Opcodes.ICONST_5);
break;
default:
if (i >= 128) {
mw.visitIntInsn(Opcodes.SIPUSH, i);
} else {
mw.visitIntInsn(Opcodes.BIPUSH, i);
}
break;
}
mw.visitInsn(Opcodes.AALOAD); // fieldWriterArray
mw.visitTypeInsn(Opcodes.CHECKCAST, TYPE_FIELD_WRITER);
mw.visitFieldInsn(Opcodes.PUTFIELD, classNameType, fieldWriter(i), DESC_FIELD_WRITER);
}
}
mw.visitInsn(Opcodes.RETURN);
mw.visitMaxs(7, 7);
}
private void genFields(List fieldWriters, ClassWriter cw, String objectWriterSupper) {
if (objectWriterSupper != TYPE_OBJECT_WRITER_ADAPTER) {
return;
}
for (int i = 0; i < fieldWriters.size(); i++) {
cw.visitField(
Opcodes.ACC_PUBLIC,
fieldWriter(i),
DESC_FIELD_WRITER
);
}
}
@Override
public FieldWriter createFieldWriter(
ObjectWriterProvider provider,
String fieldName,
int ordinal,
long features,
String format,
String label,
Field field,
ObjectWriter initObjectWriter
) {
Class> declaringClass = field.getDeclaringClass();
if (Throwable.class.isAssignableFrom(declaringClass)
|| declaringClass.getName().startsWith("java.lang")
) {
return super.createFieldWriter(provider, fieldName, ordinal, features, format, label, field, initObjectWriter);
}
Class> fieldClass = field.getType();
Type fieldType = field.getGenericType();
if (initObjectWriter != null) {
if (fieldClass == byte.class) {
fieldType = fieldClass = Byte.class;
} else if (fieldClass == short.class) {
fieldType = fieldClass = Short.class;
} else if (fieldClass == float.class) {
fieldType = fieldClass = Float.class;
} else if (fieldClass == double.class) {
fieldType = fieldClass = Double.class;
} else if (fieldClass == boolean.class) {
fieldType = fieldClass = Boolean.class;
}
FieldWriterObject objImp = new FieldWriterObject(
fieldName,
ordinal,
features,
format,
label,
fieldType,
fieldClass,
field,
null
);
objImp.initValueClass = fieldClass;
if (initObjectWriter != ObjectWriterBaseModule.VoidObjectWriter.INSTANCE) {
objImp.initObjectWriter = initObjectWriter;
}
return objImp;
}
if (fieldClass == boolean.class) {
return new FieldWriterBoolValField(fieldName, ordinal, features, format, label, field, fieldClass);
}
if (fieldClass == byte.class) {
return new FieldWriterInt8ValField(fieldName, ordinal, features, format, label, field);
}
if (fieldClass == short.class) {
return new FieldWriterInt16ValField(fieldName, ordinal, features, format, label, field);
}
if (fieldClass == int.class) {
return new FieldWriterInt32Val(fieldName, ordinal, features, format, label, field);
}
if (fieldClass == long.class) {
if (format == null || format.isEmpty()) {
return new FieldWriterInt64ValField(fieldName, ordinal, features, format, label, field);
}
return new FieldWriterMillisField(fieldName, ordinal, features, format, label, field);
}
if (fieldClass == float.class) {
return new FieldWriterFloatValField(fieldName, ordinal, features, format, label, field);
}
if (fieldClass == Float.class) {
return new FieldWriterFloatField(fieldName, ordinal, features, format, label, field);
}
if (fieldClass == double.class) {
return new FieldWriterDoubleValField(fieldName, ordinal, format, label, field);
}
if (fieldClass == Double.class) {
return new FieldWriterDoubleField(fieldName, ordinal, features, format, label, field);
}
if (fieldClass == char.class) {
return new FieldWriterCharValField(fieldName, ordinal, features, format, label, field);
}
if (fieldClass == BigInteger.class) {
return new FieldWriterBigIntField(fieldName, ordinal, features, format, label, field);
}
if (fieldClass == BigDecimal.class) {
return new FieldWriterBigDecimalField(fieldName, ordinal, features, format, label, field);
}
if (fieldClass == java.util.Date.class) {
if (format != null) {
format = format.trim();
if (format.isEmpty()) {
format = null;
}
}
return new FieldWriterDateField(fieldName, ordinal, features, format, label, field);
}
if (fieldClass == String.class) {
return new FieldWriterStringField(fieldName, ordinal, features, format, label, field);
}
if (fieldClass.isEnum()) {
BeanInfo beanInfo = new BeanInfo();
provider.getBeanInfo(beanInfo, fieldClass);
boolean writeEnumAsJavaBean = beanInfo.writeEnumAsJavaBean;
if (!writeEnumAsJavaBean) {
ObjectWriter objectWriter = provider.cache.get(fieldClass);
if (objectWriter != null && !(objectWriter instanceof ObjectWriterImplEnum)) {
writeEnumAsJavaBean = true;
}
}
Member enumValueField = BeanUtils.getEnumValueField(fieldClass, provider);
if (enumValueField == null && !writeEnumAsJavaBean) {
String[] enumAnnotationNames = BeanUtils.getEnumAnnotationNames(fieldClass);
if (enumAnnotationNames == null) {
return new FieldWriterEnum(fieldName, ordinal, features, format, label, fieldType, (Class extends Enum>) fieldClass, field, null);
}
}
}
if (fieldClass == List.class || fieldClass == ArrayList.class) {
Type itemType = null;
if (fieldType instanceof ParameterizedType) {
itemType = ((ParameterizedType) fieldType).getActualTypeArguments()[0];
}
return new FieldWriterListField(fieldName, itemType, ordinal, features, format, label, fieldType, fieldClass, field);
}
if (fieldClass.isArray()) {
Class> itemClass = fieldClass.getComponentType();
if (declaringClass == Throwable.class && "stackTrace".equals(fieldName)) {
try {
Method method = Throwable.class.getMethod("getStackTrace");
return new FieldWriterObjectArrayMethod(fieldName, itemClass, ordinal, features, format, label, fieldType, fieldClass, field, method);
} catch (NoSuchMethodException ignored) {
}
}
//
// boolean base64 = fieldClass == byte[].class && "base64".equals(format);
// if (!base64) {
// return new FieldWriterObjectArrayField(fieldName, itemClass, ordinal, features, format, label, fieldType, fieldClass, field);
// }
}
if (fieldClass == BigDecimal[].class) {
return new FieldWriterObjectArrayField<>(fieldName, BigDecimal.class, ordinal, features, format, label, BigDecimal[].class, BigDecimal[].class, field);
}
if (fieldClass == Float[].class) {
return new FieldWriterObjectArrayField<>(fieldName, Float.class, ordinal, features, format, label, Float[].class, Float[].class, field);
}
if (fieldClass == Double[].class) {
return new FieldWriterObjectArrayField<>(fieldName, Float.class, ordinal, features, format, label, Double[].class, Double[].class, field);
}
if (isFunction(fieldClass)) {
return null;
}
return new FieldWriterObject(fieldName, ordinal, features, format, label, field.getGenericType(), fieldClass, field, null);
}
void genGetObject(MethodWriterContext mwc, FieldWriter fieldWriter, int i, int OBJECT) {
MethodWriter mw = mwc.mw;
Class objectClass = mwc.objectClass;
final String TYPE_OBJECT = objectClass == null ? "java/lang/Object" : ASMUtils.type(objectClass);
Class fieldClass = fieldWriter.fieldClass;
Member member = fieldWriter.method != null ? fieldWriter.method : fieldWriter.field;
Function function = fieldWriter.getFunction();
if (member == null && function != null) {
mw.visitVarInsn(Opcodes.ALOAD, THIS);
mw.visitFieldInsn(Opcodes.GETFIELD, mwc.classNameType, fieldWriter(i), DESC_FIELD_WRITER);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_FIELD_WRITER, "getFunction", "()Ljava/util/function/Function;", false);
mw.visitVarInsn(Opcodes.ALOAD, OBJECT);
mw.visitMethodInsn(Opcodes.INVOKEINTERFACE, type(Function.class), "apply", "(Ljava/lang/Object;)Ljava/lang/Object;", true);
mw.visitTypeInsn(Opcodes.CHECKCAST, type(fieldClass));
return;
}
if (member instanceof Method) {
mw.visitVarInsn(Opcodes.ALOAD, OBJECT);
mw.visitTypeInsn(Opcodes.CHECKCAST, TYPE_OBJECT);
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_OBJECT, member.getName(), "()" + ASMUtils.desc(fieldClass), false);
return;
}
if (Modifier.isPublic(objectClass.getModifiers())
&& Modifier.isPublic(member.getModifiers())
&& !classLoader.isExternalClass(objectClass)
) {
mw.visitVarInsn(Opcodes.ALOAD, OBJECT);
mw.visitTypeInsn(Opcodes.CHECKCAST, TYPE_OBJECT);
mw.visitFieldInsn(Opcodes.GETFIELD, TYPE_OBJECT, member.getName(), ASMUtils.desc(fieldClass));
return;
}
Field field = (Field) member;
String methodName, methodDes, castToType = null;
if (fieldClass == int.class) {
methodName = "getInt";
methodDes = "(Ljava/lang/Object;J)I";
} else if (fieldClass == long.class) {
methodName = "getLong";
methodDes = "(Ljava/lang/Object;J)J";
} else if (fieldClass == float.class) {
methodName = "getFloat";
methodDes = "(Ljava/lang/Object;J)F";
} else if (fieldClass == double.class) {
methodName = "getDouble";
methodDes = "(Ljava/lang/Object;J)D";
} else if (fieldClass == char.class) {
methodName = "getChar";
methodDes = "(Ljava/lang/Object;J)C";
} else if (fieldClass == byte.class) {
methodName = "getByte";
methodDes = "(Ljava/lang/Object;J)B";
} else if (fieldClass == short.class) {
methodName = "getShort";
methodDes = "(Ljava/lang/Object;J)S";
} else if (fieldClass == boolean.class) {
methodName = "getBoolean";
methodDes = "(Ljava/lang/Object;J)Z";
} else {
methodName = "getObject";
methodDes = "(Ljava/lang/Object;J)Ljava/lang/Object;";
if (fieldClass.isEnum()) {
castToType = "java/lang/Enum";
} else if (ObjectWriterProvider.isPrimitiveOrEnum(fieldClass)) {
castToType = ASMUtils.type(fieldClass);
} else if (fieldClass.isArray() && ObjectWriterProvider.isPrimitiveOrEnum(fieldClass.getComponentType())) {
castToType = ASMUtils.type(fieldClass);
} else if (Map.class.isAssignableFrom(fieldClass)) {
castToType = "java/util/Map";
} else if (List.class.isAssignableFrom(fieldClass)) {
castToType = "java/util/List";
} else if (Collection.class.isAssignableFrom(fieldClass)) {
castToType = "java/util/Collection";
}
}
mw.visitFieldInsn(Opcodes.GETSTATIC, ObjectWriterCreatorASMUtils.TYPE_UNSAFE_UTILS, "UNSAFE", "Lsun/misc/Unsafe;");
mw.visitVarInsn(Opcodes.ALOAD, OBJECT);
mw.visitLdcInsn(
UNSAFE.objectFieldOffset(field));
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "sun/misc/Unsafe", methodName, methodDes, false);
if (castToType != null) {
mw.visitTypeInsn(Opcodes.CHECKCAST, castToType);
}
}
static class MethodWriterContext {
final ObjectWriterProvider provider;
final Class objectClass;
final long objectFeatures;
final String classNameType;
final MethodWriter mw;
final Map
© 2015 - 2025 Weber Informatics LLC | Privacy Policy