Skip to content

Commit

Permalink
add ClassLevel serializer feature config
Browse files Browse the repository at this point in the history
  • Loading branch information
wenshao committed May 3, 2016
1 parent c0dcd11 commit 7ea2219
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 30 deletions.
Expand Up @@ -30,7 +30,6 @@
import com.alibaba.fastjson.util.ASMClassLoader; import com.alibaba.fastjson.util.ASMClassLoader;
import com.alibaba.fastjson.util.ASMUtils; import com.alibaba.fastjson.util.ASMUtils;
import com.alibaba.fastjson.util.FieldInfo; import com.alibaba.fastjson.util.FieldInfo;
import com.alibaba.fastjson.util.TypeUtils;


public class ASMSerializerFactory implements Opcodes { public class ASMSerializerFactory implements Opcodes {


Expand Down Expand Up @@ -59,31 +58,27 @@ static class Context {
static int original = 7; static int original = 7;
static int processValue = 8; static int processValue = 8;


private final FieldInfo[] getters; private final FieldInfo[] getters;
private final String className; private final String className;
private final int beanSerializeFeatures; private final SerializeBeanInfo beanInfo;
private final boolean writeDirect; private final boolean writeDirect;
private final JSONType jsonType; private final JSONType jsonType;
private final int beanFeatures;


private Map<String, Integer> variants = new HashMap<String, Integer>(); private Map<String, Integer> variants = new HashMap<String, Integer>();
private int variantIndex = 9; private int variantIndex = 9;
private boolean nonContext; private boolean nonContext;


public Context(FieldInfo[] getters, JSONType jsonType, String className, int beanSerializeFeatures, public Context(FieldInfo[] getters, SerializeBeanInfo beanInfo, String className,
boolean writeDirect, boolean nonContext){ boolean writeDirect, boolean nonContext){
this.getters = getters; this.getters = getters;
this.jsonType = jsonType; this.jsonType = beanInfo.jsonType;
this.className = className; this.className = className;
this.beanSerializeFeatures = beanSerializeFeatures; this.beanInfo = beanInfo;
this.writeDirect = writeDirect; this.writeDirect = writeDirect;
this.nonContext = nonContext; this.nonContext = nonContext;
if (this.writeDirect) { if (this.writeDirect) {
processValue = 8; processValue = 8;
} }
this.beanFeatures = jsonType != null ? //
SerializerFeature.of(jsonType.serialzeFeatures()) //
: 0;
} }


public int var(String name) { public int var(String name) {
Expand Down Expand Up @@ -154,7 +149,6 @@ public ObjectSerializer createJavaBeanSerializer(SerializeBeanInfo beanInfo) thr
String packageName = ASMSerializerFactory.class.getPackage().getName(); String packageName = ASMSerializerFactory.class.getPackage().getName();
String classNameType = packageName.replace('.', '/') + "/" + className; String classNameType = packageName.replace('.', '/') + "/" + className;
String classNameFull = packageName + "." + className; String classNameFull = packageName + "." + className;
int beanSerializeFeatures = TypeUtils.getSerializeFeatures(clazz);


ClassWriter cw = new ClassWriter(); ClassWriter cw = new ClassWriter();
cw.visit(V1_5 // cw.visit(V1_5 //
Expand Down Expand Up @@ -247,7 +241,7 @@ public ObjectSerializer createJavaBeanSerializer(SerializeBeanInfo beanInfo) thr
methodName = "writeDirectNonContext"; methodName = "writeDirectNonContext";
} }


Context context = new Context(getters, jsonType, classNameType, beanSerializeFeatures, writeDirect, Context context = new Context(getters, beanInfo, classNameType, writeDirect,
nonContext); nonContext);


mw = new MethodWriter(cw, // mw = new MethodWriter(cw, //
Expand Down Expand Up @@ -339,7 +333,7 @@ public ObjectSerializer createJavaBeanSerializer(SerializeBeanInfo beanInfo) thr


if (!nativeSorted) { if (!nativeSorted) {
// sortField support // sortField support
Context context = new Context(getters, jsonType, classNameType, beanSerializeFeatures, false, Context context = new Context(getters, beanInfo, classNameType, false,
DisableCircularReferenceDetect); DisableCircularReferenceDetect);


mw = new MethodWriter(cw, ACC_PUBLIC, "writeUnsorted", mw = new MethodWriter(cw, ACC_PUBLIC, "writeUnsorted",
Expand Down Expand Up @@ -379,7 +373,7 @@ public ObjectSerializer createJavaBeanSerializer(SerializeBeanInfo beanInfo) thr
methodName = "writeAsArrayNonContext"; methodName = "writeAsArrayNonContext";
} }


Context context = new Context(getters, jsonType, classNameType, beanSerializeFeatures, writeDirect, Context context = new Context(getters, beanInfo, classNameType, writeDirect,
nonContext); nonContext);


mw = new MethodWriter(cw, ACC_PUBLIC, methodName, mw = new MethodWriter(cw, ACC_PUBLIC, methodName,
Expand Down Expand Up @@ -847,7 +841,7 @@ private void generateWriteMethod(Class<?> clazz, MethodVisitor mw, FieldInfo[] g
writeAsArrayMethodName = "writeAsArrayNormal"; writeAsArrayMethodName = "writeAsArrayNormal";
} }


if ((context.beanFeatures & SerializerFeature.BeanToArray.mask) == 0) { if ((context.beanInfo.features & SerializerFeature.BeanToArray.mask) == 0) {
Label endWriteAsArray_ = new Label(); Label endWriteAsArray_ = new Label();


mw.visitVarInsn(ALOAD, context.var("out")); mw.visitVarInsn(ALOAD, context.var("out"));
Expand Down Expand Up @@ -893,7 +887,7 @@ private void generateWriteMethod(Class<?> clazz, MethodVisitor mw, FieldInfo[] g
mw.visitVarInsn(ALOAD, context.var("parent")); mw.visitVarInsn(ALOAD, context.var("parent"));
mw.visitVarInsn(ALOAD, Context.obj); mw.visitVarInsn(ALOAD, Context.obj);
mw.visitVarInsn(ALOAD, Context.paramFieldName); mw.visitVarInsn(ALOAD, Context.paramFieldName);
mw.visitLdcInsn(context.beanSerializeFeatures); mw.visitLdcInsn(context.beanInfo.features);
mw.visitMethodInsn(INVOKEVIRTUAL, JSONSerializer, "setContext", mw.visitMethodInsn(INVOKEVIRTUAL, JSONSerializer, "setContext",
"(" + SerialContext_desc + "Ljava/lang/Object;Ljava/lang/Object;I)V"); "(" + SerialContext_desc + "Ljava/lang/Object;Ljava/lang/Object;I)V");
} }
Expand Down
43 changes: 35 additions & 8 deletions src/main/java/com/alibaba/fastjson/serializer/SerializeConfig.java
Expand Up @@ -94,15 +94,19 @@ public void setTypeKey(String typeKey) {
this.typeKey = typeKey; this.typeKey = typeKey;
} }


public final ObjectSerializer createASMSerializer(Class<?> clazz) final ObjectSerializer createASMSerializer(SerializeBeanInfo beanInfo) throws Exception {
throws Exception { return asmFactory.createJavaBeanSerializer(beanInfo);
}

public ObjectSerializer createJavaBeanSerializer(Class<?> clazz) {
SerializeBeanInfo beanInfo = TypeUtils.buildBeanInfo(clazz, null); SerializeBeanInfo beanInfo = TypeUtils.buildBeanInfo(clazz, null);
return asmFactory.createJavaBeanSerializer(beanInfo); return createJavaBeanSerializer(beanInfo);
} }


public ObjectSerializer createJavaBeanSerializer(Class<?> clazz) { public ObjectSerializer createJavaBeanSerializer(SerializeBeanInfo beanInfo) {
if (!Modifier.isPublic(clazz.getModifiers())) { Class<?> clazz = beanInfo.beanType;
return new JavaBeanSerializer(clazz); if (!Modifier.isPublic(beanInfo.beanType.getModifiers())) {
return new JavaBeanSerializer(beanInfo);
} }


boolean asm = this.asm; boolean asm = this.asm;
Expand Down Expand Up @@ -135,7 +139,7 @@ public ObjectSerializer createJavaBeanSerializer(Class<?> clazz) {


if (asm) { if (asm) {
try { try {
ObjectSerializer asmSerializer = createASMSerializer(clazz); ObjectSerializer asmSerializer = createASMSerializer(beanInfo);
if (asmSerializer != null) { if (asmSerializer != null) {
return asmSerializer; return asmSerializer;
} }
Expand All @@ -147,7 +151,7 @@ public ObjectSerializer createJavaBeanSerializer(Class<?> clazz) {
} }
} }


return new JavaBeanSerializer(clazz); return new JavaBeanSerializer(beanInfo);
} }


public boolean isAsmEnable() { public boolean isAsmEnable() {
Expand Down Expand Up @@ -246,6 +250,29 @@ public void addFilter(Class<?> clazz, SerializeFilter filter) {
} }
} }


/**
* @since 1.2.12
*/
public void config(Class<?> clazz, SerializerFeature feature, boolean value) {
ObjectSerializer serializer = getObjectWriter(clazz);

if (serializer instanceof JavaBeanSerializer) {
JavaBeanSerializer javaBeanSerializer = (JavaBeanSerializer) serializer;
SerializeBeanInfo beanInfo = javaBeanSerializer.beanInfo;
if (value) {
beanInfo.features |= feature.mask;
} else {
beanInfo.features &= ~feature.mask;
}

Class<?> serializerClass = serializer.getClass();
if (serializerClass != JavaBeanSerializer.class) {
ObjectSerializer newSerializer = this.createJavaBeanSerializer(beanInfo);
this.put(clazz, newSerializer);
}
}
}

public ObjectSerializer getObjectWriter(Class<?> clazz) { public ObjectSerializer getObjectWriter(Class<?> clazz) {
ObjectSerializer writer = serializers.get(clazz); ObjectSerializer writer = serializers.get(clazz);


Expand Down
@@ -0,0 +1,27 @@
package com.alibaba.json.bvt.serializer.filters;

import org.junit.Assert;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializeConfig;
import com.alibaba.fastjson.serializer.SerializerFeature;

import junit.framework.TestCase;

public class ClassLevelFeatureConfigTest extends TestCase {
public void test_0() throws Exception {
SerializeConfig config = new SerializeConfig();

Model model = new Model();
model.id = 1001;

Assert.assertEquals("{\"id\":1001}", JSON.toJSONString(model, config));

config.config(Model.class, SerializerFeature.BeanToArray, true);
Assert.assertEquals("[1001]", JSON.toJSONString(model, config));
}

public static class Model {
public int id;
}
}

0 comments on commit 7ea2219

Please sign in to comment.