From fe77561dedee98e7bc2b3da45c3324a77b6eb69a Mon Sep 17 00:00:00 2001 From: wenshao Date: Sun, 14 Jul 2013 11:53:24 +0800 Subject: [PATCH] support BeforeFilter --- src/main/java/com/alibaba/fastjson/JSON.java | 5 +++ .../fastjson/parser/DefaultJSONParser.java | 1 - .../serializer/ASMSerializerFactory.java | 11 ++++++ .../fastjson/serializer/BeforeFilter.java | 29 +++++++++++++++ .../fastjson/serializer/FilterUtils.java | 10 +++++ .../fastjson/serializer/JSONSerializer.java | 21 +++++++++++ .../serializer/JavaBeanSerializer.java | 5 +++ .../fastjson/serializer/MapSerializer.java | 1 - .../json/bvt/serializer/BeforeFilterTest.java | 37 +++++++++++++++++++ .../bvt/serializer/BeforeFilterTest2.java | 37 +++++++++++++++++++ 10 files changed, 155 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/alibaba/fastjson/serializer/BeforeFilter.java create mode 100644 src/test/java/com/alibaba/json/bvt/serializer/BeforeFilterTest.java create mode 100644 src/test/java/com/alibaba/json/bvt/serializer/BeforeFilterTest2.java diff --git a/src/main/java/com/alibaba/fastjson/JSON.java b/src/main/java/com/alibaba/fastjson/JSON.java index ea54fde60..0c0cd5495 100755 --- a/src/main/java/com/alibaba/fastjson/JSON.java +++ b/src/main/java/com/alibaba/fastjson/JSON.java @@ -35,6 +35,7 @@ import com.alibaba.fastjson.parser.JSONLexer; import com.alibaba.fastjson.parser.JSONToken; import com.alibaba.fastjson.parser.ParserConfig; import com.alibaba.fastjson.parser.deserializer.FieldDeserializer; +import com.alibaba.fastjson.serializer.BeforeFilter; import com.alibaba.fastjson.serializer.JSONSerializer; import com.alibaba.fastjson.serializer.NameFilter; import com.alibaba.fastjson.serializer.PropertyFilter; @@ -441,6 +442,10 @@ public abstract class JSON implements JSONStreamAware, JSONAware { if (filter instanceof PropertyFilter) { serializer.getPropertyFilters().add((PropertyFilter) filter); } + + if (filter instanceof BeforeFilter) { + serializer.getBeforeFilters().add((BeforeFilter) filter); + } } serializer.write(object); diff --git a/src/main/java/com/alibaba/fastjson/parser/DefaultJSONParser.java b/src/main/java/com/alibaba/fastjson/parser/DefaultJSONParser.java index 48dffa3d9..e582d9af3 100755 --- a/src/main/java/com/alibaba/fastjson/parser/DefaultJSONParser.java +++ b/src/main/java/com/alibaba/fastjson/parser/DefaultJSONParser.java @@ -56,7 +56,6 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONException; import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.parser.deserializer.ASMJavaBeanDeserializer; -import com.alibaba.fastjson.parser.deserializer.CollectionDeserializer; import com.alibaba.fastjson.parser.deserializer.FieldDeserializer; import com.alibaba.fastjson.parser.deserializer.IntegerDeserializer; import com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer; diff --git a/src/main/java/com/alibaba/fastjson/serializer/ASMSerializerFactory.java b/src/main/java/com/alibaba/fastjson/serializer/ASMSerializerFactory.java index 8992693ef..c0e9495ea 100755 --- a/src/main/java/com/alibaba/fastjson/serializer/ASMSerializerFactory.java +++ b/src/main/java/com/alibaba/fastjson/serializer/ASMSerializerFactory.java @@ -386,6 +386,8 @@ public class ASMSerializerFactory implements Opcodes { } mw.visitVarInsn(ISTORE, context.var("seperator")); + + _before(mw, context); for (int i = 0; i < size; ++i) { FieldInfo property = getters.get(i); @@ -1064,6 +1066,15 @@ 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"); + mw.visitVarInsn(ISTORE, context.var("seperator")); + } private void _apply(MethodVisitor mw, FieldInfo property, Context context) { Class propertyClass = property.getFieldClass(); diff --git a/src/main/java/com/alibaba/fastjson/serializer/BeforeFilter.java b/src/main/java/com/alibaba/fastjson/serializer/BeforeFilter.java new file mode 100644 index 000000000..5215c2839 --- /dev/null +++ b/src/main/java/com/alibaba/fastjson/serializer/BeforeFilter.java @@ -0,0 +1,29 @@ +package com.alibaba.fastjson.serializer; + +public abstract class BeforeFilter implements SerializeFilter { + + private final ThreadLocal serializerLocal = new ThreadLocal(); + private final ThreadLocal commaLocal = new ThreadLocal(); + + private final static Character COMMA = Character.valueOf(','); + + final char writeBefore(JSONSerializer serializer, Object object, char commaFlag) { + serializerLocal.set(serializer); + commaLocal.set(commaFlag); + writeBefore(object); + serializerLocal.set(null); + return commaLocal.get(); + } + + public abstract void writeBefore(Object object); + + public final void writeKeyValue(String key, Object value) { + JSONSerializer serializer = serializerLocal.get(); + char comma = commaLocal.get(); + serializer.writeKeyValue(comma, key, value); + if (comma != ',') { + commaLocal.set(COMMA); + } + } + +} diff --git a/src/main/java/com/alibaba/fastjson/serializer/FilterUtils.java b/src/main/java/com/alibaba/fastjson/serializer/FilterUtils.java index fa72bc3dd..92d6d2753 100755 --- a/src/main/java/com/alibaba/fastjson/serializer/FilterUtils.java +++ b/src/main/java/com/alibaba/fastjson/serializer/FilterUtils.java @@ -3,7 +3,17 @@ package com.alibaba.fastjson.serializer; import java.util.List; public class FilterUtils { + public static char writeBefore(JSONSerializer serializer, Object object, char seperator) { + List beforeFilters = serializer.getBeforeFilters(); + if (beforeFilters != null) { + for (BeforeFilter beforeFilter : beforeFilters) { + seperator = beforeFilter.writeBefore(serializer, object, seperator); + } + } + return seperator; + } + public static Object processValue(JSONSerializer serializer, Object object, String key, Object propertyValue) { List valueFilters = serializer.getValueFiltersDirect(); if (valueFilters != null) { diff --git a/src/main/java/com/alibaba/fastjson/serializer/JSONSerializer.java b/src/main/java/com/alibaba/fastjson/serializer/JSONSerializer.java index bc9684022..ac44719ab 100755 --- a/src/main/java/com/alibaba/fastjson/serializer/JSONSerializer.java +++ b/src/main/java/com/alibaba/fastjson/serializer/JSONSerializer.java @@ -48,6 +48,7 @@ public class JSONSerializer { private final SerializeWriter out; + private List beforeFilters = null; private List propertyFilters = null; private List valueFilters = null; private List nameFilters = null; @@ -251,6 +252,18 @@ public class JSONSerializer { out.write(indent); } } + + public List getBeforeFilters() { + if (beforeFilters == null) { + beforeFilters = new ArrayList(); + } + + return beforeFilters; + } + + public List getBeforeFiltersDirect() { + return beforeFilters; + } public List getNameFilters() { if (nameFilters == null) { @@ -349,6 +362,14 @@ public class JSONSerializer { public final void writeWithFieldName(Object object, Object fieldName) { writeWithFieldName(object, fieldName, null); } + + protected final void writeKeyValue(char seperator, String key, Object value) { + if (seperator != '\0') { + out.write(seperator); + } + out.writeFieldName(key); + write(value); + } public final void writeWithFieldName(Object object, Object fieldName, Type fieldType) { try { diff --git a/src/main/java/com/alibaba/fastjson/serializer/JavaBeanSerializer.java b/src/main/java/com/alibaba/fastjson/serializer/JavaBeanSerializer.java index c04e6ac0d..8f24a4a58 100755 --- a/src/main/java/com/alibaba/fastjson/serializer/JavaBeanSerializer.java +++ b/src/main/java/com/alibaba/fastjson/serializer/JavaBeanSerializer.java @@ -128,6 +128,11 @@ public class JavaBeanSerializer implements ObjectSerializer { commaFlag = true; } } + + char seperator = commaFlag ? ',':'\0'; + + char newSeperator = FilterUtils.writeBefore(serializer, object, seperator); + commaFlag = newSeperator == ','; for (int i = 0; i < getters.length; ++i) { FieldSerializer fieldSerializer = getters[i]; diff --git a/src/main/java/com/alibaba/fastjson/serializer/MapSerializer.java b/src/main/java/com/alibaba/fastjson/serializer/MapSerializer.java index 665d2f748..188474d54 100755 --- a/src/main/java/com/alibaba/fastjson/serializer/MapSerializer.java +++ b/src/main/java/com/alibaba/fastjson/serializer/MapSerializer.java @@ -18,7 +18,6 @@ package com.alibaba.fastjson.serializer; import java.io.IOException; import java.lang.reflect.Type; import java.util.LinkedHashMap; -import java.util.List; import java.util.Map; import java.util.SortedMap; import java.util.TreeMap; diff --git a/src/test/java/com/alibaba/json/bvt/serializer/BeforeFilterTest.java b/src/test/java/com/alibaba/json/bvt/serializer/BeforeFilterTest.java new file mode 100644 index 000000000..332e0f704 --- /dev/null +++ b/src/test/java/com/alibaba/json/bvt/serializer/BeforeFilterTest.java @@ -0,0 +1,37 @@ +package com.alibaba.json.bvt.serializer; + +import junit.framework.TestCase; + +import org.junit.Assert; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.serializer.BeforeFilter; + +public class BeforeFilterTest extends TestCase { + public void test_beforeFilter() throws Exception { + BeforeFilter filter = new BeforeFilter() { + + @Override + public void writeBefore(Object object) { + this.writeKeyValue("id", 123); + } + }; + Assert.assertEquals("{\"id\":123}",JSON.toJSONString( new VO(), filter)); + } + + public void test_beforeFilter2() throws Exception { + BeforeFilter filter = new BeforeFilter() { + + @Override + public void writeBefore(Object object) { + this.writeKeyValue("id", 123); + this.writeKeyValue("name", "wenshao"); + } + }; + Assert.assertEquals("{\"id\":123,\"name\":\"wenshao\"}", JSON.toJSONString(new VO(), filter)); + } + + private static class VO { + + } +} diff --git a/src/test/java/com/alibaba/json/bvt/serializer/BeforeFilterTest2.java b/src/test/java/com/alibaba/json/bvt/serializer/BeforeFilterTest2.java new file mode 100644 index 000000000..607cdd33d --- /dev/null +++ b/src/test/java/com/alibaba/json/bvt/serializer/BeforeFilterTest2.java @@ -0,0 +1,37 @@ +package com.alibaba.json.bvt.serializer; + +import junit.framework.TestCase; + +import org.junit.Assert; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.serializer.BeforeFilter; + +public class BeforeFilterTest2 extends TestCase { + public void test_beforeFilter() throws Exception { + BeforeFilter filter = new BeforeFilter() { + + @Override + public void writeBefore(Object object) { + this.writeKeyValue("id", 123); + } + }; + Assert.assertEquals(JSON.toJSONString(new VO(), filter), "{\"id\":123}"); + } + + public void test_beforeFilter2() throws Exception { + BeforeFilter filter = new BeforeFilter() { + + @Override + public void writeBefore(Object object) { + this.writeKeyValue("id", 123); + this.writeKeyValue("name", "wenshao"); + } + }; + Assert.assertEquals(JSON.toJSONString(new VO(), filter), "{\"id\":123,\"name\":\"wenshao\"}"); + } + + public static class VO { + + } +}