diff --git a/src/main/java/com/alibaba/fastjson/annotation/JSONType.java b/src/main/java/com/alibaba/fastjson/annotation/JSONType.java index 207a09552..6d0374072 100755 --- a/src/main/java/com/alibaba/fastjson/annotation/JSONType.java +++ b/src/main/java/com/alibaba/fastjson/annotation/JSONType.java @@ -5,6 +5,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import com.alibaba.fastjson.parser.Feature; import com.alibaba.fastjson.serializer.SerializerFeature; /** @@ -21,6 +22,7 @@ public @interface JSONType { String[] ignores() default {}; SerializerFeature[] serialzeFeatures() default {}; + Feature[] parseFeatures() default {}; boolean alphabetic() default true; diff --git a/src/main/java/com/alibaba/fastjson/parser/Feature.java b/src/main/java/com/alibaba/fastjson/parser/Feature.java index b06566d71..433e9da09 100755 --- a/src/main/java/com/alibaba/fastjson/parser/Feature.java +++ b/src/main/java/com/alibaba/fastjson/parser/Feature.java @@ -15,6 +15,7 @@ */ package com.alibaba.fastjson.parser; + /** * @author wenshao[szujobs@hotmail.com] */ @@ -109,4 +110,18 @@ public enum Feature { return features; } + + public static int of(Feature[] features) { + if (features == null) { + return 0; + } + + int value = 0; + + for (Feature feature: features) { + value |= feature.getMask(); + } + + return value; + } } diff --git a/src/main/java/com/alibaba/fastjson/parser/deserializer/ASMDeserializerFactory.java b/src/main/java/com/alibaba/fastjson/parser/deserializer/ASMDeserializerFactory.java index 721f98c0a..3c53c6a7f 100755 --- a/src/main/java/com/alibaba/fastjson/parser/deserializer/ASMDeserializerFactory.java +++ b/src/main/java/com/alibaba/fastjson/parser/deserializer/ASMDeserializerFactory.java @@ -323,6 +323,14 @@ public class ASMDeserializerFactory implements Opcodes { { Label next_ = new Label(); + + mw.visitVarInsn(ALOAD, 0); + mw.visitVarInsn(ALOAD, context.var("lexer")); + mw.visitMethodInsn(INVOKESPECIAL, getType(ASMJavaBeanDeserializer.class), "isSupportArrayToBean", + "(Lcom/alibaba/fastjson/parser/JSONLexer;)Z"); + mw.visitJumpInsn(IFEQ, next_); + //isSupportArrayToBean + mw.visitVarInsn(ALOAD, context.var("lexer")); mw.visitMethodInsn(INVOKEVIRTUAL, getType(JSONLexerBase.class), "token", "()I"); mw.visitFieldInsn(GETSTATIC, getType(JSONToken.class), "LBRACKET", "I"); 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 ca964b872..42b078075 100755 --- a/src/main/java/com/alibaba/fastjson/parser/deserializer/ASMJavaBeanDeserializer.java +++ b/src/main/java/com/alibaba/fastjson/parser/deserializer/ASMJavaBeanDeserializer.java @@ -90,6 +90,10 @@ public abstract class ASMJavaBeanDeserializer implements ObjectDeserializer { return ASMJavaBeanDeserializer.this.createFieldDeserializer(mapping, clazz, fieldInfo); } } + + public boolean isSupportArrayToBean(JSONLexer lexer) { + return serializer.isSupportArrayToBean(lexer); + } public Object parseRest(DefaultJSONParser parser, Type type, Object fieldName, Object instance) { // serializer.parseField(parser, key, object, objectType, fieldValues) 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 51a6bb434..141e861ec 100755 --- a/src/main/java/com/alibaba/fastjson/parser/deserializer/JavaBeanDeserializer.java +++ b/src/main/java/com/alibaba/fastjson/parser/deserializer/JavaBeanDeserializer.java @@ -193,7 +193,7 @@ public class JavaBeanDeserializer implements ObjectDeserializer { return (T) object; } - if (lexer.token() == JSONToken.LBRACKET && lexer.isEnabled(Feature.SupportArrayToBean)) { + if (lexer.token() == JSONToken.LBRACKET && isSupportArrayToBean(lexer)) { return deserialzeArrayMapping(parser, type, fieldName, object); } @@ -428,4 +428,8 @@ public class JavaBeanDeserializer implements ObjectDeserializer { public List getSortedFieldDeserializers() { return sortedFieldDeserializers; } + + public final boolean isSupportArrayToBean(JSONLexer lexer) { + return Feature.isEnabled(beanInfo.getParserFeatures(), Feature.SupportArrayToBean) || lexer.isEnabled(Feature.SupportArrayToBean); + } } diff --git a/src/main/java/com/alibaba/fastjson/serializer/ASMSerializerFactory.java b/src/main/java/com/alibaba/fastjson/serializer/ASMSerializerFactory.java index ba6edaab3..41e5a76a3 100755 --- a/src/main/java/com/alibaba/fastjson/serializer/ASMSerializerFactory.java +++ b/src/main/java/com/alibaba/fastjson/serializer/ASMSerializerFactory.java @@ -467,11 +467,11 @@ public class ASMSerializerFactory implements Opcodes { { Label endWriteAsArray_ = new Label(); + mw.visitVarInsn(ALOAD, 0); + mw.visitFieldInsn(GETFIELD, context.getClassName(), "nature", getDesc(JavaBeanSerializer.class)); 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.visitMethodInsn(INVOKEVIRTUAL, getType(JavaBeanSerializer.class), "isWriteAsArray", + "(Lcom/alibaba/fastjson/serializer/JSONSerializer;)Z"); mw.visitJumpInsn(IFEQ, endWriteAsArray_); // ///// diff --git a/src/main/java/com/alibaba/fastjson/serializer/JSONSerializer.java b/src/main/java/com/alibaba/fastjson/serializer/JSONSerializer.java index 31819a8d9..2c7e4f31e 100755 --- a/src/main/java/com/alibaba/fastjson/serializer/JSONSerializer.java +++ b/src/main/java/com/alibaba/fastjson/serializer/JSONSerializer.java @@ -537,14 +537,4 @@ public class JSONSerializer { this.out.close(); } - public final boolean isWriteAsArray(Object object, Type fieldType) { - boolean writeAsArray; - if (out.isEnabled(SerializerFeature.BeanToArray)) { - writeAsArray = true; - } else { - writeAsArray = false; - } - - return writeAsArray; - } } diff --git a/src/main/java/com/alibaba/fastjson/serializer/JavaBeanSerializer.java b/src/main/java/com/alibaba/fastjson/serializer/JavaBeanSerializer.java index 7e5f948c2..b4782fa0a 100755 --- a/src/main/java/com/alibaba/fastjson/serializer/JavaBeanSerializer.java +++ b/src/main/java/com/alibaba/fastjson/serializer/JavaBeanSerializer.java @@ -26,7 +26,6 @@ import java.util.Map; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONException; -import com.alibaba.fastjson.annotation.JSONType; import com.alibaba.fastjson.util.FieldInfo; import com.alibaba.fastjson.util.TypeUtils; @@ -114,7 +113,7 @@ public class JavaBeanSerializer implements ObjectSerializer { SerialContext parent = serializer.getContext(); serializer.setContext(parent, object, fieldName, features); - final boolean writeAsArray = serializer.isWriteAsArray(object, fieldType); + final boolean writeAsArray = isWriteAsArray(serializer); try { final char startSeperator = writeAsArray ? '[' : '{'; @@ -263,4 +262,19 @@ public class JavaBeanSerializer implements ObjectSerializer { return new ObjectFieldSerializer(fieldInfo); } + + public boolean isWriteAsArray(JSONSerializer serializer) { + if (SerializerFeature.isEnabled(features, SerializerFeature.BeanToArray)) { + return true; + } + + boolean writeAsArray; + if (serializer.isEnabled(SerializerFeature.BeanToArray)) { + writeAsArray = true; + } else { + writeAsArray = false; + } + + return writeAsArray; + } } diff --git a/src/main/java/com/alibaba/fastjson/util/DeserializeBeanInfo.java b/src/main/java/com/alibaba/fastjson/util/DeserializeBeanInfo.java index b56dc104a..2210c1c72 100755 --- a/src/main/java/com/alibaba/fastjson/util/DeserializeBeanInfo.java +++ b/src/main/java/com/alibaba/fastjson/util/DeserializeBeanInfo.java @@ -30,9 +30,12 @@ public class DeserializeBeanInfo { private final List fieldList = new ArrayList(); private final List sortedFieldList = new ArrayList(); + private int parserFeatures = 0; + public DeserializeBeanInfo(Class clazz){ super(); this.clazz = clazz; + this.parserFeatures = TypeUtils.getParserFeatures(clazz); } public Constructor getDefaultConstructor() { @@ -125,7 +128,8 @@ public class DeserializeBeanInfo { Field field = TypeUtils.getField(clazz, fieldAnnotation.name()); final int ordinal = fieldAnnotation.ordinal(); final int serialzeFeatures = SerializerFeature.of(fieldAnnotation.serialzeFeatures()); - FieldInfo fieldInfo = new FieldInfo(fieldAnnotation.name(), clazz, fieldClass, fieldType, field, ordinal, serialzeFeatures); + FieldInfo fieldInfo = new FieldInfo(fieldAnnotation.name(), clazz, fieldClass, fieldType, field, + ordinal, serialzeFeatures); beanInfo.add(fieldInfo); } return beanInfo; @@ -199,10 +203,10 @@ public class DeserializeBeanInfo { if (!annotation.deserialize()) { continue; } - + ordinal = annotation.ordinal(); serialzeFeatures = SerializerFeature.of(annotation.serialzeFeatures()); - + if (annotation.name().length() != 0) { String propertyName = annotation.name(); beanInfo.add(new FieldInfo(propertyName, method, null, clazz, type, ordinal, serialzeFeatures)); @@ -228,7 +232,7 @@ public class DeserializeBeanInfo { propertyName = methodName.substring(4); } else if (c3 == 'f') { propertyName = methodName.substring(3); - } else if (methodName.length()>=5 && Character.isUpperCase(methodName.charAt(4))){ + } else if (methodName.length() >= 5 && Character.isUpperCase(methodName.charAt(4))) { propertyName = TypeUtils.decapitalize(methodName.substring(3)); } else { continue; @@ -242,11 +246,11 @@ public class DeserializeBeanInfo { if (field != null) { JSONField fieldAnnotation = field.getAnnotation(JSONField.class); - + if (fieldAnnotation != null) { ordinal = fieldAnnotation.ordinal(); serialzeFeatures = SerializerFeature.of(fieldAnnotation.serialzeFeatures()); - + if (fieldAnnotation.name().length() != 0) { propertyName = fieldAnnotation.name(); beanInfo.add(new FieldInfo(propertyName, method, field, clazz, type, ordinal, serialzeFeatures)); @@ -285,7 +289,7 @@ public class DeserializeBeanInfo { if (fieldAnnotation != null) { ordinal = fieldAnnotation.ordinal(); serialzeFeatures = SerializerFeature.of(fieldAnnotation.serialzeFeatures()); - + if (fieldAnnotation.name().length() != 0) { propertyName = fieldAnnotation.name(); } @@ -400,4 +404,8 @@ public class DeserializeBeanInfo { return factoryMethod; } + + public int getParserFeatures() { + return parserFeatures; + } } diff --git a/src/main/java/com/alibaba/fastjson/util/TypeUtils.java b/src/main/java/com/alibaba/fastjson/util/TypeUtils.java index 373743821..2c32cfdaf 100755 --- a/src/main/java/com/alibaba/fastjson/util/TypeUtils.java +++ b/src/main/java/com/alibaba/fastjson/util/TypeUtils.java @@ -51,6 +51,7 @@ import com.alibaba.fastjson.JSONException; import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.annotation.JSONField; import com.alibaba.fastjson.annotation.JSONType; +import com.alibaba.fastjson.parser.Feature; import com.alibaba.fastjson.parser.JSONScanner; import com.alibaba.fastjson.parser.ParserConfig; import com.alibaba.fastjson.parser.deserializer.FieldDeserializer; @@ -1319,6 +1320,16 @@ public class TypeUtils { return SerializerFeature.of(annotation.serialzeFeatures()); } + public static int getParserFeatures(Class clazz) { + JSONType annotation = clazz.getAnnotation(JSONType.class); + + if (annotation == null) { + return 0; + } + + return Feature.of(annotation.parseFeatures()); + } + public static String decapitalize(String name) { if (name == null || name.length() == 0) { return name; diff --git a/src/test/java/com/alibaba/json/bvt/writeAsArray/WriteAsArray_jsonType.java b/src/test/java/com/alibaba/json/bvt/writeAsArray/WriteAsArray_jsonType.java new file mode 100644 index 000000000..17b888fe6 --- /dev/null +++ b/src/test/java/com/alibaba/json/bvt/writeAsArray/WriteAsArray_jsonType.java @@ -0,0 +1,67 @@ +package com.alibaba.json.bvt.writeAsArray; + +import junit.framework.TestCase; + +import org.junit.Assert; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.annotation.JSONField; +import com.alibaba.fastjson.annotation.JSONType; +import com.alibaba.fastjson.parser.Feature; +import com.alibaba.fastjson.serializer.SerializerFeature; + +public class WriteAsArray_jsonType extends TestCase { + + public void test_0() throws Exception { + VO vo = new VO(); + vo.setId(123); + vo.setName("wenshao"); + + Parent parent = new Parent(); + parent.setVo(vo); + + String text = JSON.toJSONString(parent); + Assert.assertEquals("{\"vo\":[123,\"wenshao\"]}", text); + VO vo2 = JSON.parseObject(text, Parent.class).getVo(); + Assert.assertEquals(vo.getId(), vo2.getId()); + Assert.assertEquals(vo.getName(), vo2.getName()); + } + + public static class Parent { + private VO vo; + + public VO getVo() { + return vo; + } + + public void setVo(VO vo) { + this.vo = vo; + } + + } + + @JSONType(serialzeFeatures=SerializerFeature.BeanToArray, parseFeatures=Feature.SupportArrayToBean) + public static class VO { + @JSONField(ordinal=1) + private int id; + + @JSONField(ordinal=2) + private String name; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } +}