mirror of
https://github.com/alibaba/fastjson.git
synced 2026-10-24 10:20:34 +08:00
support writeJavaBeanAsArray
This commit is contained in:
@@ -1524,6 +1524,7 @@ public abstract class JSONLexer implements Closeable {
|
||||
return list;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public Collection<String> scanStringArray(Class<?> type, int expectNextChar) {
|
||||
matchStat = UNKOWN;
|
||||
|
||||
|
||||
@@ -246,6 +246,29 @@ public class ASMSerializerFactory implements Opcodes {
|
||||
mw.visitEnd();
|
||||
}
|
||||
|
||||
// writeAsArray
|
||||
{
|
||||
Context context = new Context(className);
|
||||
|
||||
mw = cw.visitMethod(ACC_PUBLIC,
|
||||
"writeAsArray",
|
||||
"(Lcom/alibaba/fastjson/serializer/JSONSerializer;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/reflect/Type;)V",
|
||||
null, new String[] { "java/io/IOException" });
|
||||
|
||||
mw.visitVarInsn(ALOAD, context.serializer()); // serializer
|
||||
mw.visitMethodInsn(INVOKEVIRTUAL, getType(JSONSerializer.class), "getWriter",
|
||||
"()" + getDesc(SerializeWriter.class));
|
||||
mw.visitVarInsn(ASTORE, context.var("out"));
|
||||
|
||||
mw.visitVarInsn(ALOAD, context.obj()); // obj
|
||||
mw.visitTypeInsn(CHECKCAST, getType(clazz)); // serializer
|
||||
mw.visitVarInsn(ASTORE, context.var("entity")); // obj
|
||||
generateWriteAsArray(clazz, mw, sortedGetters, context);
|
||||
mw.visitInsn(RETURN);
|
||||
mw.visitMaxs(5, context.getVariantCount() + 1);
|
||||
mw.visitEnd();
|
||||
}
|
||||
|
||||
byte[] code = cw.toByteArray();
|
||||
//
|
||||
// org.apache.commons.io.IOUtils.write(code, new java.io.FileOutputStream(
|
||||
@@ -258,6 +281,89 @@ public class ASMSerializerFactory implements Opcodes {
|
||||
return (ObjectSerializer) instance;
|
||||
}
|
||||
|
||||
private void generateWriteAsArray(Class<?> clazz, MethodVisitor mw, List<FieldInfo> getters, Context context)
|
||||
throws Exception {
|
||||
|
||||
mw.visitVarInsn(ALOAD, context.var("out"));
|
||||
mw.visitVarInsn(BIPUSH, '[');
|
||||
mw.visitMethodInsn(INVOKEVIRTUAL, getType(SerializeWriter.class), "write", "(C)V");
|
||||
|
||||
int size = getters.size();
|
||||
for (int i = 0; i < size; ++i) {
|
||||
final char seperator = (i == size - 1) ? ']' : ',';
|
||||
|
||||
FieldInfo property = getters.get(i);
|
||||
Class<?> propertyClass = property.getFieldClass();
|
||||
|
||||
mw.visitLdcInsn(property.getName());
|
||||
mw.visitVarInsn(ASTORE, context.fieldName());
|
||||
|
||||
if (propertyClass == byte.class) {
|
||||
throw new JSONException("TODO : " + propertyClass);
|
||||
} else if (propertyClass == short.class) {
|
||||
throw new JSONException("TODO : " + propertyClass);
|
||||
} else if (propertyClass == int.class) {
|
||||
mw.visitVarInsn(ALOAD, context.var("out"));
|
||||
_get(mw, context, property);
|
||||
mw.visitVarInsn(BIPUSH, seperator);
|
||||
mw.visitMethodInsn(INVOKEVIRTUAL, getType(SerializeWriter.class), "writeIntAndChar", "(IC)V");
|
||||
} else if (propertyClass == long.class) {
|
||||
mw.visitVarInsn(ALOAD, context.var("out"));
|
||||
_get(mw, context, property);
|
||||
mw.visitVarInsn(BIPUSH, seperator);
|
||||
mw.visitMethodInsn(INVOKEVIRTUAL, getType(SerializeWriter.class), "writeLongAndChar", "(JC)V");
|
||||
} else if (propertyClass == float.class) {
|
||||
throw new JSONException("TODO : " + propertyClass);
|
||||
} else if (propertyClass == double.class) {
|
||||
throw new JSONException("TODO : " + propertyClass);
|
||||
} else if (propertyClass == boolean.class) {
|
||||
throw new JSONException("TODO : " + propertyClass);
|
||||
} else if (propertyClass == char.class) {
|
||||
throw new JSONException("TODO : " + propertyClass);
|
||||
} else if (propertyClass == String.class) {
|
||||
mw.visitVarInsn(ALOAD, context.var("out"));
|
||||
_get(mw, context, property);
|
||||
mw.visitVarInsn(BIPUSH, seperator);
|
||||
mw.visitMethodInsn(INVOKEVIRTUAL, getType(SerializeWriter.class), "writeString",
|
||||
"(Ljava/lang/String;C)V");
|
||||
} else if (propertyClass == BigDecimal.class) {
|
||||
throw new JSONException("TODO : " + propertyClass);
|
||||
} else if (List.class.isAssignableFrom(propertyClass)) {
|
||||
throw new JSONException("TODO : " + propertyClass);
|
||||
} else if (propertyClass.isEnum()) {
|
||||
throw new JSONException("TODO : " + propertyClass);
|
||||
} else {
|
||||
String format = property.getFormat();
|
||||
|
||||
mw.visitVarInsn(ALOAD, context.serializer());
|
||||
_get(mw, context, property);
|
||||
if (format != null) {
|
||||
mw.visitLdcInsn(format);
|
||||
mw.visitMethodInsn(INVOKEVIRTUAL, getType(JSONSerializer.class), "writeWithFormat",
|
||||
"(Ljava/lang/Object;Ljava/lang/String;)V");
|
||||
} else {
|
||||
mw.visitVarInsn(ALOAD, context.fieldName());
|
||||
if (property.getFieldType() instanceof Class<?> //
|
||||
&& ((Class<?>) property.getFieldType()).isPrimitive()) {
|
||||
mw.visitMethodInsn(INVOKEVIRTUAL, getType(JSONSerializer.class), "writeWithFieldName",
|
||||
"(Ljava/lang/Object;Ljava/lang/Object;)V");
|
||||
} else {
|
||||
mw.visitVarInsn(ALOAD, 0);
|
||||
mw.visitFieldInsn(GETFIELD, context.getClassName(), property.getName() + "_asm_fieldType",
|
||||
"Ljava/lang/reflect/Type;");
|
||||
|
||||
mw.visitMethodInsn(INVOKEVIRTUAL, getType(JSONSerializer.class), "writeWithFieldName",
|
||||
"(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/reflect/Type;)V");
|
||||
}
|
||||
}
|
||||
|
||||
mw.visitVarInsn(ALOAD, context.var("out"));
|
||||
mw.visitVarInsn(BIPUSH, seperator);
|
||||
mw.visitMethodInsn(INVOKEVIRTUAL, getType(SerializeWriter.class), "write", "(C)V");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void generateWriteMethod(Class<?> clazz, MethodVisitor mw, List<FieldInfo> getters, Context context)
|
||||
throws Exception {
|
||||
Label end = new Label();
|
||||
@@ -329,6 +435,30 @@ public class ASMSerializerFactory implements Opcodes {
|
||||
mw.visitLabel(endRef_);
|
||||
}
|
||||
|
||||
{
|
||||
Label endWriteAsArray_ = new Label();
|
||||
|
||||
mw.visitVarInsn(ALOAD, context.serializer());
|
||||
mw.visitVarInsn(ALOAD, context.obj());
|
||||
mw.visitVarInsn(ALOAD, context.paramFieldType());
|
||||
mw.visitMethodInsn(INVOKEVIRTUAL, getType(JSONSerializer.class), "isWriteAsArray",
|
||||
"(Ljava/lang/Object;Ljava/lang/reflect/Type;)Z");
|
||||
mw.visitJumpInsn(IFEQ, endWriteAsArray_);
|
||||
|
||||
// /////
|
||||
mw.visitVarInsn(ALOAD, 0); // this
|
||||
mw.visitVarInsn(ALOAD, 1); // serializer
|
||||
mw.visitVarInsn(ALOAD, 2); // obj
|
||||
mw.visitVarInsn(ALOAD, 3); // fieldObj
|
||||
mw.visitVarInsn(ALOAD, 4); // fieldType
|
||||
mw.visitMethodInsn(INVOKEVIRTUAL, context.getClassName(), "writeAsArray",
|
||||
"(Lcom/alibaba/fastjson/serializer/JSONSerializer;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/reflect/Type;)V");
|
||||
|
||||
mw.visitInsn(RETURN);
|
||||
|
||||
mw.visitLabel(endWriteAsArray_);
|
||||
}
|
||||
|
||||
{
|
||||
mw.visitVarInsn(ALOAD, context.serializer());
|
||||
mw.visitMethodInsn(INVOKEVIRTUAL, getType(JSONSerializer.class), "getContext",
|
||||
@@ -386,7 +516,7 @@ public class ASMSerializerFactory implements Opcodes {
|
||||
}
|
||||
|
||||
mw.visitVarInsn(ISTORE, context.var("seperator"));
|
||||
|
||||
|
||||
_before(mw, context);
|
||||
|
||||
for (int i = 0; i < size; ++i) {
|
||||
@@ -1011,16 +1141,7 @@ public class ASMSerializerFactory implements Opcodes {
|
||||
}
|
||||
|
||||
private void _writeObject(MethodVisitor mw, FieldInfo fieldInfo, Context context, Label _end) {
|
||||
String format = null;
|
||||
JSONField annotation = fieldInfo.getAnnotation(JSONField.class);
|
||||
|
||||
if (annotation != null) {
|
||||
format = annotation.format();
|
||||
|
||||
if (format.trim().length() == 0) {
|
||||
format = null;
|
||||
}
|
||||
}
|
||||
String format = fieldInfo.getFormat();
|
||||
|
||||
Label _not_null = new Label();
|
||||
|
||||
@@ -1041,7 +1162,7 @@ public class ASMSerializerFactory implements Opcodes {
|
||||
mw.visitMethodInsn(INVOKEVIRTUAL, getType(SerializeWriter.class), "writeFieldName", "(Ljava/lang/String;)V");
|
||||
|
||||
// serializer.write(obj)
|
||||
mw.visitVarInsn(ALOAD, context.serializer()); // serializer
|
||||
mw.visitVarInsn(ALOAD, context.serializer());
|
||||
mw.visitVarInsn(ALOAD, context.processValue());
|
||||
if (format != null) {
|
||||
mw.visitLdcInsn(format);
|
||||
@@ -1049,12 +1170,11 @@ public class ASMSerializerFactory implements Opcodes {
|
||||
"(Ljava/lang/Object;Ljava/lang/String;)V");
|
||||
} else {
|
||||
mw.visitVarInsn(ALOAD, context.fieldName());
|
||||
if (fieldInfo.getFieldType() instanceof Class<?> && ((Class<?>) fieldInfo.getFieldType()).isPrimitive()) {
|
||||
if (fieldInfo.getFieldType() instanceof Class<?> //
|
||||
&& ((Class<?>) fieldInfo.getFieldType()).isPrimitive()) {
|
||||
mw.visitMethodInsn(INVOKEVIRTUAL, getType(JSONSerializer.class), "writeWithFieldName",
|
||||
"(Ljava/lang/Object;Ljava/lang/Object;)V");
|
||||
} else {
|
||||
// fieldInfo.getName() + "_asm_fieldType"
|
||||
|
||||
mw.visitVarInsn(ALOAD, 0);
|
||||
mw.visitFieldInsn(GETFIELD, context.getClassName(), fieldInfo.getName() + "_asm_fieldType",
|
||||
"Ljava/lang/reflect/Type;");
|
||||
@@ -1066,13 +1186,13 @@ public class ASMSerializerFactory implements Opcodes {
|
||||
|
||||
_seperator(mw, context);
|
||||
}
|
||||
|
||||
|
||||
private void _before(MethodVisitor mw, Context context) {
|
||||
mw.visitVarInsn(ALOAD, context.serializer());
|
||||
mw.visitVarInsn(ALOAD, context.obj());
|
||||
mw.visitVarInsn(ILOAD, context.var("seperator"));
|
||||
mw.visitMethodInsn(INVOKESTATIC, getType(FilterUtils.class), "writeBefore",
|
||||
"(Lcom/alibaba/fastjson/serializer/JSONSerializer;Ljava/lang/Object;C)C");
|
||||
"(Lcom/alibaba/fastjson/serializer/JSONSerializer;Ljava/lang/Object;C)C");
|
||||
mw.visitVarInsn(ISTORE, context.var("seperator"));
|
||||
}
|
||||
|
||||
|
||||
@@ -520,4 +520,15 @@ public class JSONSerializer {
|
||||
public void close() {
|
||||
this.out.close();
|
||||
}
|
||||
|
||||
public final boolean isWriteAsArray(Object object, Type fieldType) {
|
||||
boolean writeAsArray;
|
||||
if (out.isEnabled(SerializerFeature.WriteJavaBeanAsArray)) {
|
||||
writeAsArray = true;
|
||||
} else {
|
||||
writeAsArray = false;
|
||||
}
|
||||
|
||||
return writeAsArray;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ public class JavaBeanSerializer implements ObjectSerializer {
|
||||
protected boolean isWriteClassName(JSONSerializer serializer, Object obj, Type fieldType, Object fieldName) {
|
||||
return serializer.isWriteClassName(fieldType, obj);
|
||||
}
|
||||
|
||||
|
||||
public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType) throws IOException {
|
||||
SerializeWriter out = serializer.getWriter();
|
||||
|
||||
@@ -110,12 +110,7 @@ public class JavaBeanSerializer implements ObjectSerializer {
|
||||
SerialContext parent = serializer.getContext();
|
||||
serializer.setContext(parent, object, fieldName);
|
||||
|
||||
boolean writeAsArray;
|
||||
if (out.isEnabled(SerializerFeature.WriteJavaBeanAsArray)) {
|
||||
writeAsArray = true;
|
||||
} else {
|
||||
writeAsArray = false;
|
||||
}
|
||||
final boolean writeAsArray = serializer.isWriteAsArray(object, fieldType);
|
||||
|
||||
try {
|
||||
final char startSeperator = writeAsArray ? '[' : '{';
|
||||
|
||||
@@ -9,6 +9,8 @@ import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.lang.reflect.TypeVariable;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
|
||||
public class FieldInfo implements Comparable<FieldInfo> {
|
||||
|
||||
private final String name;
|
||||
@@ -214,6 +216,20 @@ public class FieldInfo implements Comparable<FieldInfo> {
|
||||
|
||||
return annotation;
|
||||
}
|
||||
|
||||
public String getFormat() {
|
||||
String format = null;
|
||||
JSONField annotation = getAnnotation(JSONField.class);
|
||||
|
||||
if (annotation != null) {
|
||||
format = annotation.format();
|
||||
|
||||
if (format.trim().length() == 0) {
|
||||
format = null;
|
||||
}
|
||||
}
|
||||
return format;
|
||||
}
|
||||
|
||||
public Object get(Object javaObject) throws IllegalAccessException, InvocationTargetException {
|
||||
if (method != null) {
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@ import org.junit.Assert;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.serializer.SerializerFeature;
|
||||
|
||||
public class WriteAsArray_0 extends TestCase {
|
||||
public class WriteAsArray_0_private extends TestCase {
|
||||
public void test_0 () throws Exception {
|
||||
VO vo = new VO();
|
||||
vo.setId(123);
|
||||
Reference in New Issue
Block a user