diff --git a/src/main/java/com/alibaba/fastjson/JSON.java b/src/main/java/com/alibaba/fastjson/JSON.java index 22fbcb008..7efdd3a37 100755 --- a/src/main/java/com/alibaba/fastjson/JSON.java +++ b/src/main/java/com/alibaba/fastjson/JSON.java @@ -34,9 +34,10 @@ import com.alibaba.fastjson.parser.Feature; import com.alibaba.fastjson.parser.JSONLexer; import com.alibaba.fastjson.parser.JSONToken; import com.alibaba.fastjson.parser.ParserConfig; +import com.alibaba.fastjson.parser.deserializer.ExtraProcessor; +import com.alibaba.fastjson.parser.deserializer.ExtraTypeProvider; import com.alibaba.fastjson.parser.deserializer.FieldDeserializer; import com.alibaba.fastjson.parser.deserializer.ParseProcess; -import com.alibaba.fastjson.parser.deserializer.ExtraProcessor; import com.alibaba.fastjson.serializer.BeforeFilter; import com.alibaba.fastjson.serializer.JSONSerializer; import com.alibaba.fastjson.serializer.NameFilter; @@ -231,8 +232,12 @@ public abstract class JSON implements JSONStreamAware, JSONAware { DefaultJSONParser parser = new DefaultJSONParser(input, config, featureValues); + if (processor instanceof ExtraTypeProvider) { + parser.getExtraTypeProviders().add((ExtraTypeProvider) processor); + } + if (processor instanceof ExtraProcessor) { - parser.getRedudantProcessors().add((ExtraProcessor) processor); + parser.getExtraProcessors().add((ExtraProcessor) processor); } T value = (T) parser.parseObject(clazz); diff --git a/src/main/java/com/alibaba/fastjson/parser/DefaultJSONParser.java b/src/main/java/com/alibaba/fastjson/parser/DefaultJSONParser.java index 447bba445..d17b87ad5 100755 --- a/src/main/java/com/alibaba/fastjson/parser/DefaultJSONParser.java +++ b/src/main/java/com/alibaba/fastjson/parser/DefaultJSONParser.java @@ -56,6 +56,8 @@ 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.ExtraProcessor; +import com.alibaba.fastjson.parser.deserializer.ExtraTypeProvider; import com.alibaba.fastjson.parser.deserializer.FieldDeserializer; import com.alibaba.fastjson.parser.deserializer.IntegerDeserializer; import com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer; @@ -63,7 +65,6 @@ import com.alibaba.fastjson.parser.deserializer.ListResolveFieldDeserializer; import com.alibaba.fastjson.parser.deserializer.LongDeserializer; import com.alibaba.fastjson.parser.deserializer.MapResolveFieldDeserializer; import com.alibaba.fastjson.parser.deserializer.ObjectDeserializer; -import com.alibaba.fastjson.parser.deserializer.ExtraProcessor; import com.alibaba.fastjson.parser.deserializer.StringDeserializer; import com.alibaba.fastjson.util.TypeUtils; @@ -96,7 +97,8 @@ public class DefaultJSONParser extends AbstractJSONParser implements Closeable { private int resolveStatus = NONE; - private List redudantProcessors = null; + private List extraTypeProviders = null; + private List extraProcessors = null; static { primitiveClasses.add(boolean.class); @@ -1073,17 +1075,28 @@ public class DefaultJSONParser extends AbstractJSONParser implements Closeable { return resolveTaskList.get(resolveTaskList.size() - 1); } - public List getRedudantProcessors() { - if (redudantProcessors == null) { - redudantProcessors = new ArrayList(2); + public List getExtraProcessors() { + if (extraProcessors == null) { + extraProcessors = new ArrayList(2); } - return redudantProcessors; + return extraProcessors; + } + + public List getExtraProcessorsDirect() { + return extraProcessors; + } + + public List getExtraTypeProviders() { + if (extraTypeProviders == null) { + extraTypeProviders = new ArrayList(2); + } + return extraTypeProviders; } - public List getRedudantProcessorsDirect() { - return redudantProcessors; + public List getExtraTypeProvidersDirect() { + return extraTypeProviders; } - + public void setContext(ParseContext context) { if (isEnabled(Feature.DisableCircularReferenceDetect)) { return; diff --git a/src/main/java/com/alibaba/fastjson/parser/deserializer/ASMJavaBeanDeserializer.java b/src/main/java/com/alibaba/fastjson/parser/deserializer/ASMJavaBeanDeserializer.java index f1d82a6b9..ca964b872 100755 --- a/src/main/java/com/alibaba/fastjson/parser/deserializer/ASMJavaBeanDeserializer.java +++ b/src/main/java/com/alibaba/fastjson/parser/deserializer/ASMJavaBeanDeserializer.java @@ -3,12 +3,9 @@ package com.alibaba.fastjson.parser.deserializer; import java.lang.reflect.Type; import java.util.Map; -import com.alibaba.fastjson.JSONException; import com.alibaba.fastjson.parser.DefaultJSONParser; -import com.alibaba.fastjson.parser.Feature; import com.alibaba.fastjson.parser.JSONLexer; import com.alibaba.fastjson.parser.ParserConfig; -import com.alibaba.fastjson.serializer.FilterUtils; import com.alibaba.fastjson.util.FieldInfo; public abstract class ASMJavaBeanDeserializer implements ObjectDeserializer { @@ -69,14 +66,7 @@ public abstract class ASMJavaBeanDeserializer implements ObjectDeserializer { } if (fieldDeserializer == null) { - if (!parser.isEnabled(Feature.IgnoreNotMatch)) { - throw new JSONException("setter not found, class " + serializer.getClass() + ", property " + key); - } - - lexer.nextTokenWithColon(); - Object value = parser.parse(); - FilterUtils.processRedundant(parser, object, key, value); - + this.serializer.parseExtra(parser, object, key); return false; } diff --git a/src/main/java/com/alibaba/fastjson/parser/deserializer/ExtraProcessor.java b/src/main/java/com/alibaba/fastjson/parser/deserializer/ExtraProcessor.java index 71b7bc778..a4802f8de 100644 --- a/src/main/java/com/alibaba/fastjson/parser/deserializer/ExtraProcessor.java +++ b/src/main/java/com/alibaba/fastjson/parser/deserializer/ExtraProcessor.java @@ -2,6 +2,7 @@ package com.alibaba.fastjson.parser.deserializer; + public interface ExtraProcessor extends ParseProcess { - void process(Object object, String key, Object value); + void processExtra(Object object, String key, Object value); } diff --git a/src/main/java/com/alibaba/fastjson/parser/deserializer/ExtraTypeProvider.java b/src/main/java/com/alibaba/fastjson/parser/deserializer/ExtraTypeProvider.java new file mode 100644 index 000000000..d85032c00 --- /dev/null +++ b/src/main/java/com/alibaba/fastjson/parser/deserializer/ExtraTypeProvider.java @@ -0,0 +1,8 @@ +package com.alibaba.fastjson.parser.deserializer; + +import java.lang.reflect.Type; + + +public interface ExtraTypeProvider extends ParseProcess { + Type getExtraType(Object object, String key); +} diff --git a/src/main/java/com/alibaba/fastjson/parser/deserializer/JavaBeanDeserializer.java b/src/main/java/com/alibaba/fastjson/parser/deserializer/JavaBeanDeserializer.java index 2d5231712..70eaab90e 100755 --- a/src/main/java/com/alibaba/fastjson/parser/deserializer/JavaBeanDeserializer.java +++ b/src/main/java/com/alibaba/fastjson/parser/deserializer/JavaBeanDeserializer.java @@ -329,13 +329,7 @@ public class JavaBeanDeserializer implements ObjectDeserializer { } if (fieldDeserializer == null) { - if (!parser.isEnabled(Feature.IgnoreNotMatch)) { - throw new JSONException("setter not found, class " + clazz.getName() + ", property " + key); - } - - lexer.nextTokenWithColon(); - Object value = parser.parse(); // skip - FilterUtils.processRedundant(parser, object, key, value); + parseExtra(parser, object, key); return false; } @@ -347,6 +341,24 @@ public class JavaBeanDeserializer implements ObjectDeserializer { return true; } + void parseExtra(DefaultJSONParser parser, Object object, String key) { + final JSONLexer lexer = parser.getLexer(); // xxx + if (!lexer.isEnabled(Feature.IgnoreNotMatch)) { + throw new JSONException("setter not found, class " + clazz.getName() + ", property " + key); + } + + lexer.nextTokenWithColon(); + Type type = FilterUtils.getExtratype(parser, object, key); + Object value; + if (type == null) { + value = parser.parse(); // skip + } else { + value = parser.parseObject(type); + } + + FilterUtils.processExtra(parser, object, key, value); + } + public int getFastMatchToken() { return JSONToken.LBRACE; } diff --git a/src/main/java/com/alibaba/fastjson/serializer/FilterUtils.java b/src/main/java/com/alibaba/fastjson/serializer/FilterUtils.java index ee2070b6e..81d0168fa 100755 --- a/src/main/java/com/alibaba/fastjson/serializer/FilterUtils.java +++ b/src/main/java/com/alibaba/fastjson/serializer/FilterUtils.java @@ -1,19 +1,33 @@ package com.alibaba.fastjson.serializer; +import java.lang.reflect.Type; import java.util.List; import com.alibaba.fastjson.parser.DefaultJSONParser; import com.alibaba.fastjson.parser.deserializer.ExtraProcessor; +import com.alibaba.fastjson.parser.deserializer.ExtraTypeProvider; public class FilterUtils { - - public static void processRedundant(DefaultJSONParser parser, Object object, String key, Object value) { - List redudantProcessors = parser.getRedudantProcessorsDirect(); - if (redudantProcessors == null) { + public static Type getExtratype(DefaultJSONParser parser, Object object, String key) { + List extraTypeProviders = parser.getExtraTypeProvidersDirect(); + if (extraTypeProviders == null) { + return null; + } + + Type type = null; + for (ExtraTypeProvider extraProvider : extraTypeProviders) { + type = extraProvider.getExtraType(object, key); + } + return type; + } + + public static void processExtra(DefaultJSONParser parser, Object object, String key, Object value) { + List extraProcessors = parser.getExtraProcessorsDirect(); + if (extraProcessors == null) { return; } - for (ExtraProcessor process : redudantProcessors) { - process.process(object, key, value); + for (ExtraProcessor process : extraProcessors) { + process.processExtra(object, key, value); } } diff --git a/src/test/java/com/alibaba/json/bvt/parser/RedundantTest.java b/src/test/java/com/alibaba/json/bvt/parser/RedundantTest.java index c3d419dba..3d240d1f9 100644 --- a/src/test/java/com/alibaba/json/bvt/parser/RedundantTest.java +++ b/src/test/java/com/alibaba/json/bvt/parser/RedundantTest.java @@ -1,5 +1,6 @@ package com.alibaba.json.bvt.parser; +import java.lang.reflect.Type; import java.util.HashMap; import java.util.Map; @@ -9,12 +10,13 @@ import org.junit.Assert; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.parser.deserializer.ExtraProcessor; +import com.alibaba.fastjson.parser.deserializer.ExtraTypeProvider; public class RedundantTest extends TestCase { - public void test_0() throws Exception { + public void test_extra() throws Exception { ExtraProcessor processor = new ExtraProcessor() { - public void process(Object object, String key, Object value) { + public void processExtra(Object object, String key, Object value) { VO vo = (VO) object; vo.getAttributes().put(key, value); } @@ -24,6 +26,28 @@ public class RedundantTest extends TestCase { Assert.assertEquals(123, vo.getId()); Assert.assertEquals("abc", vo.getAttributes().get("name")); } + + public void test_extraWithType() throws Exception { + class MyExtraProcessor implements ExtraProcessor, ExtraTypeProvider { + public void processExtra(Object object, String key, Object value) { + VO vo = (VO) object; + vo.getAttributes().put(key, value); + } + + public Type getExtraType(Object object, String key) { + if ("value".equals(key)) { + return int.class; + } + return null; + } + }; + ExtraProcessor processor = new MyExtraProcessor(); + + VO vo = JSON.parseObject("{\"id\":123,\"value\":\"123456\"}", VO.class, processor); + Assert.assertEquals(123, vo.getId()); + Assert.assertEquals(123456, vo.getAttributes().get("value")); + } + public static class VO {