From 708b5c5eb4d2b90d1ee5eba125a77ff3ee8052f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=AB=98=E9=93=81?= Date: Thu, 5 May 2016 09:34:51 +0800 Subject: [PATCH] BeanToArray support field level config --- .../fastjson/parser/JSONLexerBase.java | 4 ++ .../deserializer/ASMDeserializerFactory.java | 71 ++++++++++++------- .../deserializer/JavaBeanDeserializer.java | 25 +++++-- .../serializer/ASMSerializerFactory.java | 10 ++- .../fastjson/serializer/FieldSerializer.java | 11 +-- .../serializer/JavaBeanSerializer.java | 21 +++++- .../com/alibaba/fastjson/util/FieldInfo.java | 7 +- .../alibaba/fastjson/util/JavaBeanInfo.java | 31 ++++---- .../com/alibaba/fastjson/util/TypeUtils.java | 18 +++-- .../bvt/parser/array/BeanToArrayTest3.java | 35 +++++++++ .../alibaba/json/bvt/util/FieldInfoTest.java | 10 +-- .../json/test/codegen/DepartmentCodec.java | 2 +- src/test/java/data/media/ImageGenDecoder.java | 2 +- .../data/media/MediaContentGenDecoder.java | 2 +- src/test/java/data/media/MediaGenDecoder.java | 2 +- 15 files changed, 181 insertions(+), 70 deletions(-) create mode 100644 src/test/java/com/alibaba/json/bvt/parser/array/BeanToArrayTest3.java diff --git a/src/main/java/com/alibaba/fastjson/parser/JSONLexerBase.java b/src/main/java/com/alibaba/fastjson/parser/JSONLexerBase.java index 08df361246..b19e2dbf7d 100755 --- a/src/main/java/com/alibaba/fastjson/parser/JSONLexerBase.java +++ b/src/main/java/com/alibaba/fastjson/parser/JSONLexerBase.java @@ -521,6 +521,10 @@ public final boolean isEnabled(Feature feature) { public final boolean isEnabled(int feature) { return (this.features & feature) != 0; } + + public final boolean isEnabled(int features, int feature) { + return (this.features & feature) != 0 || (features & feature) != 0; + } public abstract String numberString(); 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 40cb6f6f9c..6b5fce44dd 100755 --- a/src/main/java/com/alibaba/fastjson/parser/deserializer/ASMDeserializerFactory.java +++ b/src/main/java/com/alibaba/fastjson/parser/deserializer/ASMDeserializerFactory.java @@ -72,25 +72,11 @@ public ObjectDeserializer createJavaBeanDeserializer(ParserConfig config, Class< _init(cw, new Context(classNameType, config, beanInfo, 3)); _createInstance(cw, new Context(classNameType, config, beanInfo, 3)); - _deserialze(cw, new Context(classNameType, config, beanInfo, 4)); + _deserialze(cw, new Context(classNameType, config, beanInfo, 5)); _deserialzeArrayMapping(cw, new Context(classNameType, config, beanInfo, 4)); byte[] code = cw.toByteArray(); - // if (JSON.DUMP_CLASS != null) { - // FileOutputStream fos = null; - // try { - // fos = new FileOutputStream(JSON.DUMP_CLASS + File.separator + className + ".class"); - // fos.write(code); - // } catch (Exception ex) { - // System.err.println("FASTJSON dump class:" + className + "失败:" + ex.getMessage()); - // } finally { - // if (fos != null) { - // fos.close(); - // } - // } - // } - Class exampleClass = defineClassPublic(classNameFull, code, 0, code.length); Constructor constructor = exampleClass.getConstructor(ParserConfig.class, Class.class); @@ -318,7 +304,7 @@ private void _deserialzeArrayMapping(ClassWriter cw, Context context) { mw.visitLdcInsn(com.alibaba.fastjson.parser.JSONToken.LBRACKET); mw.visitMethodInsn(INVOKEVIRTUAL, JSONLexerBase, "nextToken", "(I)V"); - mw.visitVarInsn(ALOAD, 1); // parser + mw.visitVarInsn(ALOAD, Context.parser); mw.visitVarInsn(ALOAD, 0); mw.visitLdcInsn(i); mw.visitMethodInsn(INVOKEVIRTUAL, type(JavaBeanDeserializer.class), "getFieldType", @@ -462,7 +448,7 @@ private void _deserialze(ClassWriter cw, Context context) { context.fieldInfoList = beanInfo.sortedFields; MethodVisitor mw = new MethodWriter(cw, ACC_PUBLIC, "deserialze", - "(L" + DefaultJSONParser + ";Ljava/lang/reflect/Type;Ljava/lang/Object;)Ljava/lang/Object;", + "(L" + DefaultJSONParser + ";Ljava/lang/reflect/Type;Ljava/lang/Object;I)Ljava/lang/Object;", null, null); Label reset_ = new Label(); @@ -484,16 +470,17 @@ private void _deserialze(ClassWriter cw, Context context) { if ((beanInfo.parserFeatures & Feature.SupportArrayToBean.mask) == 0) { mw.visitVarInsn(ALOAD, context.var("lexer")); + mw.visitVarInsn(ILOAD, 4); mw.visitLdcInsn(Feature.SupportArrayToBean.mask); - mw.visitMethodInsn(INVOKEVIRTUAL, JSONLexerBase, "isEnabled", "(I)Z"); + mw.visitMethodInsn(INVOKEVIRTUAL, JSONLexerBase, "isEnabled", "(II)Z"); mw.visitJumpInsn(IFEQ, next_); } mw.visitVarInsn(ALOAD, 0); - mw.visitVarInsn(ALOAD, 1); + mw.visitVarInsn(ALOAD, Context.parser); mw.visitVarInsn(ALOAD, 2); mw.visitVarInsn(ALOAD, 3); - mw.visitVarInsn(ALOAD, 4); + mw.visitInsn(ACONST_NULL); //mw.visitVarInsn(ALOAD, 5); mw.visitMethodInsn(INVOKESPECIAL, // context.className, // "deserialzeArrayMapping", // @@ -790,9 +777,10 @@ private void _deserialze(ClassWriter cw, Context context) { mw.visitVarInsn(ALOAD, 2); mw.visitVarInsn(ALOAD, 3); mw.visitVarInsn(ALOAD, context.var("instance")); + mw.visitVarInsn(ILOAD, 4); mw.visitMethodInsn(INVOKEVIRTUAL, type(JavaBeanDeserializer.class), "parseRest", "(L" + DefaultJSONParser - + ";Ljava/lang/reflect/Type;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); + + ";Ljava/lang/reflect/Type;Ljava/lang/Object;Ljava/lang/Object;I)Ljava/lang/Object;"); mw.visitTypeInsn(CHECKCAST, type(context.clazz)); // cast mw.visitInsn(ARETURN); @@ -801,12 +789,13 @@ private void _deserialze(ClassWriter cw, Context context) { mw.visitVarInsn(ALOAD, 1); mw.visitVarInsn(ALOAD, 2); mw.visitVarInsn(ALOAD, 3); + mw.visitVarInsn(ILOAD, 4); mw.visitMethodInsn(INVOKESPECIAL, type(JavaBeanDeserializer.class), // "deserialze", // - "(L" + DefaultJSONParser + ";Ljava/lang/reflect/Type;Ljava/lang/Object;)Ljava/lang/Object;"); + "(L" + DefaultJSONParser + ";Ljava/lang/reflect/Type;Ljava/lang/Object;I)Ljava/lang/Object;"); mw.visitInsn(ARETURN); - mw.visitMaxs(5, context.variantIndex); + mw.visitMaxs(6, context.variantIndex); mw.visitEnd(); } @@ -1343,6 +1332,34 @@ private void _deserialze_obj(Context context, MethodVisitor mw, Label reset_, Fi private void _deserObject(Context context, MethodVisitor mw, FieldInfo fieldInfo, Class fieldClass, int i) { _getFieldDeser(context, mw, fieldInfo); + Label instanceOfElse_ = new Label(), instanceOfEnd_ = new Label(); + if ((fieldInfo.parserFeatures & Feature.SupportArrayToBean.mask) != 0) { + mw.visitInsn(DUP); + mw.visitTypeInsn(INSTANCEOF, type(JavaBeanDeserializer.class)); + mw.visitJumpInsn(IFEQ, instanceOfElse_); + + mw.visitTypeInsn(CHECKCAST, type(JavaBeanDeserializer.class)); // cast + mw.visitVarInsn(ALOAD, 1); + if (fieldInfo.fieldType instanceof Class) { + mw.visitLdcInsn(com.alibaba.fastjson.asm.Type.getType(desc(fieldInfo.fieldClass))); + } else { + mw.visitVarInsn(ALOAD, 0); + mw.visitLdcInsn(i); + mw.visitMethodInsn(INVOKEVIRTUAL, type(JavaBeanDeserializer.class), "getFieldType", + "(I)Ljava/lang/reflect/Type;"); + } + mw.visitLdcInsn(fieldInfo.name); + mw.visitLdcInsn(fieldInfo.parserFeatures); + mw.visitMethodInsn(INVOKEVIRTUAL, type(JavaBeanDeserializer.class), "deserialze", + "(L" + DefaultJSONParser + ";Ljava/lang/reflect/Type;Ljava/lang/Object;I)Ljava/lang/Object;"); + mw.visitTypeInsn(CHECKCAST, type(fieldClass)); // cast + mw.visitVarInsn(ASTORE, context.var(fieldInfo.name + "_asm")); + + mw.visitJumpInsn(GOTO, instanceOfEnd_); + + mw.visitLabel(instanceOfElse_); + } + mw.visitVarInsn(ALOAD, 1); if (fieldInfo.fieldType instanceof Class) { mw.visitLdcInsn(com.alibaba.fastjson.asm.Type.getType(desc(fieldInfo.fieldClass))); @@ -1357,6 +1374,8 @@ private void _deserObject(Context context, MethodVisitor mw, FieldInfo fieldInfo "(L" + DefaultJSONParser + ";Ljava/lang/reflect/Type;Ljava/lang/Object;)Ljava/lang/Object;"); mw.visitTypeInsn(CHECKCAST, type(fieldClass)); // cast mw.visitVarInsn(ASTORE, context.var(fieldInfo.name + "_asm")); + + mw.visitLabel(instanceOfEnd_); } private void _getFieldDeser(Context context, MethodVisitor mw, FieldInfo fieldInfo) { @@ -1383,7 +1402,11 @@ private void _getFieldDeser(Context context, MethodVisitor mw, FieldInfo fieldIn static class Context { - private int variantIndex = 5; + static final int parser = 1; + static final int type = 2; + static final int fieldName = 3; + + private int variantIndex = -1; private final Map variants = new HashMap(); private final Class clazz; 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 79313ffbb6..377fca4046 100755 --- a/src/main/java/com/alibaba/fastjson/parser/deserializer/JavaBeanDeserializer.java +++ b/src/main/java/com/alibaba/fastjson/parser/deserializer/JavaBeanDeserializer.java @@ -126,9 +126,13 @@ public Object createInstance(DefaultJSONParser parser, Type type) { return object; } - + public T deserialze(DefaultJSONParser parser, Type type, Object fieldName) { - return deserialze(parser, type, fieldName, null); + return deserialze(parser, type, fieldName, 0); + } + + public T deserialze(DefaultJSONParser parser, Type type, Object fieldName, int features) { + return deserialze(parser, type, fieldName, null, features); } @SuppressWarnings({ "unchecked" }) @@ -206,7 +210,11 @@ protected Enum scanEnum(JSONLexer lexer, char seperator) { } @SuppressWarnings({ "unchecked", "rawtypes" }) - protected T deserialze(DefaultJSONParser parser, Type type, Object fieldName, Object object) { + protected T deserialze(DefaultJSONParser parser, // + Type type, // + Object fieldName, // + Object object, // + int features) { if (type == JSON.class || type == JSONObject.class) { return (T) parser.parse(); } @@ -237,8 +245,11 @@ protected T deserialze(DefaultJSONParser parser, Type type, Object fieldName } if (token == JSONToken.LBRACKET) { - boolean isSupportArrayToBean = (beanInfo.parserFeatures & Feature.SupportArrayToBean.mask) != 0 - || lexer.isEnabled(Feature.SupportArrayToBean); + final int mask = Feature.SupportArrayToBean.mask; + boolean isSupportArrayToBean = (beanInfo.parserFeatures & mask) != 0 // + || lexer.isEnabled(Feature.SupportArrayToBean) // + || (features & mask) != 0 + ; if (isSupportArrayToBean) { return deserialzeArrayMapping(parser, type, fieldName, object); } @@ -707,8 +718,8 @@ public Type getFieldType(int ordinal) { return sortedFieldDeserializers[ordinal].fieldInfo.fieldType; } - protected Object parseRest(DefaultJSONParser parser, Type type, Object fieldName, Object instance) { - Object value = deserialze(parser, type, fieldName, instance); + protected Object parseRest(DefaultJSONParser parser, Type type, Object fieldName, Object instance, int features) { + Object value = deserialze(parser, type, fieldName, instance, features); return value; } diff --git a/src/main/java/com/alibaba/fastjson/serializer/ASMSerializerFactory.java b/src/main/java/com/alibaba/fastjson/serializer/ASMSerializerFactory.java index e74da5da84..db2a1e7d25 100755 --- a/src/main/java/com/alibaba/fastjson/serializer/ASMSerializerFactory.java +++ b/src/main/java/com/alibaba/fastjson/serializer/ASMSerializerFactory.java @@ -1571,9 +1571,13 @@ private void _writeObject(MethodVisitor mw, FieldInfo fieldInfo, Context context mw.visitTypeInsn(INSTANCEOF, JavaBeanSerializer); mw.visitJumpInsn(IFEQ, instanceOfElse_); - String writeMethodName = context.nonContext && context.writeDirect ? // - "writeDirectNonContext" // - : "write"; + boolean fieldBeanToArray = (fieldInfo.serialzeFeatures & SerializerFeature.BeanToArray.mask) != 0; + String writeMethodName; + if (context.nonContext && context.writeDirect) { + writeMethodName = fieldBeanToArray ? "writeAsArrayNonContext" : "writeDirectNonContext"; + } else { + writeMethodName = fieldBeanToArray ? "writeAsArray" : "write"; + } mw.visitVarInsn(ALOAD, context.var("fied_ser")); mw.visitTypeInsn(CHECKCAST, JavaBeanSerializer); // cast diff --git a/src/main/java/com/alibaba/fastjson/serializer/FieldSerializer.java b/src/main/java/com/alibaba/fastjson/serializer/FieldSerializer.java index 6118bece33..19a3b7ea2a 100755 --- a/src/main/java/com/alibaba/fastjson/serializer/FieldSerializer.java +++ b/src/main/java/com/alibaba/fastjson/serializer/FieldSerializer.java @@ -175,13 +175,16 @@ public void writeValue(JSONSerializer serializer, Object propertyValue) throws E } Class valueClass = propertyValue.getClass(); + ObjectSerializer valueSerializer; if (valueClass == runtimeInfo.runtimeFieldClass) { - runtimeInfo.fieldSerializer.write(serializer, propertyValue, fieldInfo.name, fieldInfo.fieldType, fieldFeatures); - return; + valueSerializer = runtimeInfo.fieldSerializer; + } else { + valueSerializer = serializer.getObjectWriter(valueClass); } - - ObjectSerializer valueSerializer = serializer.getObjectWriter(valueClass); + valueSerializer.write(serializer, propertyValue, fieldInfo.name, fieldInfo.fieldType, fieldFeatures); + + } static class RuntimeSerializerInfo { diff --git a/src/main/java/com/alibaba/fastjson/serializer/JavaBeanSerializer.java b/src/main/java/com/alibaba/fastjson/serializer/JavaBeanSerializer.java index 3eea8a7bc4..458941ac9b 100644 --- a/src/main/java/com/alibaba/fastjson/serializer/JavaBeanSerializer.java +++ b/src/main/java/com/alibaba/fastjson/serializer/JavaBeanSerializer.java @@ -86,6 +86,14 @@ public void writeDirectNonContext(JSONSerializer serializer, // write(serializer, object, fieldName, fieldType, features); } + public void writeAsArray(JSONSerializer serializer, // + Object object, // + Object fieldName, // + Type fieldType, // + int features) throws IOException { + write(serializer, object, fieldName, fieldType, features); + } + public void writeAsArrayNonContext(JSONSerializer serializer, // Object object, // Object fieldName, // @@ -121,7 +129,7 @@ public void write(JSONSerializer serializer, // SerialContext parent = serializer.context; serializer.setContext(parent, object, fieldName, this.beanInfo.features, features); - final boolean writeAsArray = isWriteAsArray(serializer); + final boolean writeAsArray = isWriteAsArray(serializer, features); try { final char startSeperator = writeAsArray ? '[' : '{'; @@ -342,9 +350,16 @@ public boolean writeReference(JSONSerializer serializer, Object object, int fiel return false; } } - + protected boolean isWriteAsArray(JSONSerializer serializer) { - return (beanInfo.features & SerializerFeature.BeanToArray.mask) != 0 || serializer.out.beanToArray; + return isWriteAsArray(serializer, 0); + } + + protected boolean isWriteAsArray(JSONSerializer serializer, int fieldFeatrues) { + final int mask = SerializerFeature.BeanToArray.mask; + return (beanInfo.features & mask) != 0 // + || serializer.out.beanToArray // + || (fieldFeatrues & mask) != 0; } public Object getFieldValue(Object object, String key) { diff --git a/src/main/java/com/alibaba/fastjson/util/FieldInfo.java b/src/main/java/com/alibaba/fastjson/util/FieldInfo.java index 65405d0317..5ddf84c199 100755 --- a/src/main/java/com/alibaba/fastjson/util/FieldInfo.java +++ b/src/main/java/com/alibaba/fastjson/util/FieldInfo.java @@ -27,6 +27,7 @@ public class FieldInfo implements Comparable { public final Class declaringClass; public final boolean getOnly; public final int serialzeFeatures; + public final int parserFeatures; public final String label; private final JSONField fieldAnnotation; @@ -45,7 +46,8 @@ public FieldInfo(String name, // Type fieldType, // Field field, // int ordinal, // - int serialzeFeatures){ + int serialzeFeatures, // + int parserFeatures){ this.name = name; this.declaringClass = declaringClass; this.fieldClass = fieldClass; @@ -54,6 +56,7 @@ public FieldInfo(String name, // this.field = field; this.ordinal = ordinal; this.serialzeFeatures = serialzeFeatures; + this.parserFeatures = 0; isEnum = fieldClass.isEnum(); @@ -85,6 +88,7 @@ public FieldInfo(String name, // Type type, // int ordinal, // int serialzeFeatures, // + int parserFeatures, // JSONField fieldAnnotation, // JSONField methodAnnotation, // String label){ @@ -100,6 +104,7 @@ public FieldInfo(String name, // this.field = field; this.ordinal = ordinal; this.serialzeFeatures = serialzeFeatures; + this.parserFeatures = parserFeatures; this.fieldAnnotation = fieldAnnotation; this.methodAnnotation = methodAnnotation; diff --git a/src/main/java/com/alibaba/fastjson/util/JavaBeanInfo.java b/src/main/java/com/alibaba/fastjson/util/JavaBeanInfo.java index e7b093b4ab..9cab656bcf 100644 --- a/src/main/java/com/alibaba/fastjson/util/JavaBeanInfo.java +++ b/src/main/java/com/alibaba/fastjson/util/JavaBeanInfo.java @@ -20,6 +20,7 @@ import com.alibaba.fastjson.annotation.JSONField; import com.alibaba.fastjson.annotation.JSONPOJOBuilder; import com.alibaba.fastjson.annotation.JSONType; +import com.alibaba.fastjson.parser.Feature; import com.alibaba.fastjson.serializer.SerializerFeature; public class JavaBeanInfo { @@ -163,8 +164,9 @@ public static JavaBeanInfo build(Class clazz, Type type) { Field field = TypeUtils.getField(clazz, fieldAnnotation.name(), declaredFields); final int ordinal = fieldAnnotation.ordinal(); final int serialzeFeatures = SerializerFeature.of(fieldAnnotation.serialzeFeatures()); + final int parserFeatures = Feature.of(fieldAnnotation.parseFeatures()); FieldInfo fieldInfo = new FieldInfo(fieldAnnotation.name(), clazz, fieldClass, fieldType, field, - ordinal, serialzeFeatures); + ordinal, serialzeFeatures, parserFeatures); add(fieldList, fieldInfo); } } @@ -197,8 +199,9 @@ public static JavaBeanInfo build(Class clazz, Type type) { Field field = TypeUtils.getField(clazz, fieldAnnotation.name(), declaredFields); final int ordinal = fieldAnnotation.ordinal(); final int serialzeFeatures = SerializerFeature.of(fieldAnnotation.serialzeFeatures()); + final int parserFeatures = Feature.of(fieldAnnotation.parseFeatures()); FieldInfo fieldInfo = new FieldInfo(fieldAnnotation.name(), clazz, fieldClass, fieldType, field, - ordinal, serialzeFeatures); + ordinal, serialzeFeatures, parserFeatures); add(fieldList, fieldInfo); } } @@ -234,7 +237,7 @@ public static JavaBeanInfo build(Class clazz, Type type) { continue; } - int ordinal = 0, serialzeFeatures = 0; + int ordinal = 0, serialzeFeatures = 0, parserFeatures = 0; JSONField annotation = method.getAnnotation(JSONField.class); @@ -249,10 +252,11 @@ public static JavaBeanInfo build(Class clazz, Type type) { ordinal = annotation.ordinal(); serialzeFeatures = SerializerFeature.of(annotation.serialzeFeatures()); + parserFeatures = Feature.of(annotation.parseFeatures()); if (annotation.name().length() != 0) { String propertyName = annotation.name(); - add(fieldList, new FieldInfo(propertyName, method, null, clazz, type, ordinal, serialzeFeatures, + add(fieldList, new FieldInfo(propertyName, method, null, clazz, type, ordinal, serialzeFeatures, parserFeatures, annotation, null, null)); continue; } @@ -278,7 +282,7 @@ public static JavaBeanInfo build(Class clazz, Type type) { String propertyName = properNameBuilder.toString(); - add(fieldList, new FieldInfo(propertyName, method, null, clazz, type, ordinal, serialzeFeatures, + add(fieldList, new FieldInfo(propertyName, method, null, clazz, type, ordinal, serialzeFeatures, parserFeatures, annotation, null, null)); } @@ -321,7 +325,7 @@ public static JavaBeanInfo build(Class clazz, Type type) { } for (Method method : methods) { // - int ordinal = 0, serialzeFeatures = 0; + int ordinal = 0, serialzeFeatures = 0, parserFeatures = 0; String methodName = method.getName(); if (methodName.length() < 4) { continue; @@ -353,10 +357,11 @@ public static JavaBeanInfo build(Class clazz, Type type) { ordinal = annotation.ordinal(); serialzeFeatures = SerializerFeature.of(annotation.serialzeFeatures()); + parserFeatures = Feature.of(annotation.parseFeatures()); if (annotation.name().length() != 0) { String propertyName = annotation.name(); - add(fieldList, new FieldInfo(propertyName, method, null, clazz, type, ordinal, serialzeFeatures, + add(fieldList, new FieldInfo(propertyName, method, null, clazz, type, ordinal, serialzeFeatures, parserFeatures, annotation, null, null)); continue; } @@ -400,18 +405,19 @@ public static JavaBeanInfo build(Class clazz, Type type) { if (fieldAnnotation != null) { ordinal = fieldAnnotation.ordinal(); serialzeFeatures = SerializerFeature.of(fieldAnnotation.serialzeFeatures()); + parserFeatures = Feature.of(fieldAnnotation.parseFeatures()); if (fieldAnnotation.name().length() != 0) { propertyName = fieldAnnotation.name(); add(fieldList, new FieldInfo(propertyName, method, field, clazz, type, ordinal, - serialzeFeatures, annotation, fieldAnnotation, null)); + serialzeFeatures, parserFeatures, annotation, fieldAnnotation, null)); continue; } } } - add(fieldList, new FieldInfo(propertyName, method, field, clazz, type, ordinal, serialzeFeatures, + add(fieldList, new FieldInfo(propertyName, method, field, clazz, type, ordinal, serialzeFeatures, parserFeatures, annotation, fieldAnnotation, null)); } @@ -432,7 +438,7 @@ public static JavaBeanInfo build(Class clazz, Type type) { continue; } - int ordinal = 0, serialzeFeatures = 0; + int ordinal = 0, serialzeFeatures = 0, parserFeatures = 0; String propertyName = field.getName(); JSONField fieldAnnotation = field.getAnnotation(JSONField.class); @@ -440,12 +446,13 @@ public static JavaBeanInfo build(Class clazz, Type type) { if (fieldAnnotation != null) { ordinal = fieldAnnotation.ordinal(); serialzeFeatures = SerializerFeature.of(fieldAnnotation.serialzeFeatures()); + parserFeatures = Feature.of(fieldAnnotation.parseFeatures()); if (fieldAnnotation.name().length() != 0) { propertyName = fieldAnnotation.name(); } } - add(fieldList, new FieldInfo(propertyName, null, field, clazz, type, ordinal, serialzeFeatures, null, + add(fieldList, new FieldInfo(propertyName, null, field, clazz, type, ordinal, serialzeFeatures, parserFeatures, null, fieldAnnotation, null)); } @@ -484,7 +491,7 @@ public static JavaBeanInfo build(Class clazz, Type type) { continue; } - add(fieldList, new FieldInfo(propertyName, method, null, clazz, type, 0, 0, annotation, null, null)); + add(fieldList, new FieldInfo(propertyName, method, null, clazz, type, 0, 0, 0, annotation, null, null)); } } } diff --git a/src/main/java/com/alibaba/fastjson/util/TypeUtils.java b/src/main/java/com/alibaba/fastjson/util/TypeUtils.java index a4b3cf2800..ffa134095c 100755 --- a/src/main/java/com/alibaba/fastjson/util/TypeUtils.java +++ b/src/main/java/com/alibaba/fastjson/util/TypeUtils.java @@ -1092,7 +1092,7 @@ public static List computeGetters(Class clazz, // for (Method method : clazz.getMethods()) { String methodName = method.getName(); - int ordinal = 0, serialzeFeatures = 0; + int ordinal = 0, serialzeFeatures = 0, parserFeatures = 0; String label = null; if (Modifier.isStatic(method.getModifiers())) { @@ -1129,6 +1129,7 @@ public static List computeGetters(Class clazz, // ordinal = annotation.ordinal(); serialzeFeatures = SerializerFeature.of(annotation.serialzeFeatures()); + parserFeatures = Feature.of(annotation.parseFeatures()); if (annotation.name().length() != 0) { String propertyName = annotation.name(); @@ -1141,7 +1142,7 @@ public static List computeGetters(Class clazz, // } FieldInfo fieldInfo = new FieldInfo(propertyName, method, null, clazz, null, ordinal, - serialzeFeatures, annotation, null, label); + serialzeFeatures, parserFeatures, annotation, null, label); fieldInfoMap.put(propertyName, fieldInfo); continue; } @@ -1199,6 +1200,7 @@ public static List computeGetters(Class clazz, // ordinal = fieldAnnotation.ordinal(); serialzeFeatures = SerializerFeature.of(fieldAnnotation.serialzeFeatures()); + parserFeatures = Feature.of(fieldAnnotation.parseFeatures()); if (fieldAnnotation.name().length() != 0) { propertyName = fieldAnnotation.name(); @@ -1224,7 +1226,7 @@ public static List computeGetters(Class clazz, // } } - FieldInfo fieldInfo = new FieldInfo(propertyName, method, field, clazz, null, ordinal, serialzeFeatures, + FieldInfo fieldInfo = new FieldInfo(propertyName, method, field, clazz, null, ordinal, serialzeFeatures, parserFeatures, annotation, fieldAnnotation, label); fieldInfoMap.put(propertyName, fieldInfo); } @@ -1268,7 +1270,8 @@ public static List computeGetters(Class clazz, // ordinal = fieldAnnotation.ordinal(); serialzeFeatures = SerializerFeature.of(fieldAnnotation.serialzeFeatures()); - + parserFeatures = Feature.of(fieldAnnotation.parseFeatures()); + if (fieldAnnotation.name().length() != 0) { propertyName = fieldAnnotation.name(); @@ -1293,7 +1296,7 @@ public static List computeGetters(Class clazz, // } } - FieldInfo fieldInfo = new FieldInfo(propertyName, method, field, clazz, null, ordinal, serialzeFeatures, + FieldInfo fieldInfo = new FieldInfo(propertyName, method, field, clazz, null, ordinal, serialzeFeatures, parserFeatures, annotation, fieldAnnotation, label); fieldInfoMap.put(propertyName, fieldInfo); } @@ -1306,7 +1309,7 @@ public static List computeGetters(Class clazz, // JSONField fieldAnnotation = field.getAnnotation(JSONField.class); - int ordinal = 0, serialzeFeatures = 0; + int ordinal = 0, serialzeFeatures = 0, parserFeatures = 0; String propertyName = field.getName(); String label = null; if (fieldAnnotation != null) { @@ -1316,6 +1319,7 @@ public static List computeGetters(Class clazz, // ordinal = fieldAnnotation.ordinal(); serialzeFeatures = SerializerFeature.of(fieldAnnotation.serialzeFeatures()); + parserFeatures = Feature.of(fieldAnnotation.parseFeatures()); if (fieldAnnotation.name().length() != 0) { propertyName = fieldAnnotation.name(); @@ -1334,7 +1338,7 @@ public static List computeGetters(Class clazz, // } if (!fieldInfoMap.containsKey(propertyName)) { - FieldInfo fieldInfo = new FieldInfo(propertyName, null, field, clazz, null, ordinal, serialzeFeatures, + FieldInfo fieldInfo = new FieldInfo(propertyName, null, field, clazz, null, ordinal, serialzeFeatures, parserFeatures, null, fieldAnnotation, label); fieldInfoMap.put(propertyName, fieldInfo); } diff --git a/src/test/java/com/alibaba/json/bvt/parser/array/BeanToArrayTest3.java b/src/test/java/com/alibaba/json/bvt/parser/array/BeanToArrayTest3.java new file mode 100644 index 0000000000..6fa8427bf2 --- /dev/null +++ b/src/test/java/com/alibaba/json/bvt/parser/array/BeanToArrayTest3.java @@ -0,0 +1,35 @@ +package com.alibaba.json.bvt.parser.array; + +import org.junit.Assert; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.annotation.JSONField; +import com.alibaba.fastjson.parser.Feature; +import com.alibaba.fastjson.serializer.SerializerFeature; + +import junit.framework.TestCase; + +public class BeanToArrayTest3 extends TestCase { + + public void test_array() throws Exception { + Model model = new Model(); + model.item = new Item(); + model.item.id = 1001; + + String text = JSON.toJSONString(model); + + Assert.assertEquals("{\"item\":[1001]}", text); + + Model model2 = JSON.parseObject(text, Model.class); + Assert.assertEquals(model2.item.id, model.item.id); + } + + public static class Model { + @JSONField(serialzeFeatures=SerializerFeature.BeanToArray, parseFeatures=Feature.SupportArrayToBean) + public Item item; + } + + public static class Item { + public int id; + } +} diff --git a/src/test/java/com/alibaba/json/bvt/util/FieldInfoTest.java b/src/test/java/com/alibaba/json/bvt/util/FieldInfoTest.java index d411b082c3..f79854640e 100755 --- a/src/test/java/com/alibaba/json/bvt/util/FieldInfoTest.java +++ b/src/test/java/com/alibaba/json/bvt/util/FieldInfoTest.java @@ -14,18 +14,18 @@ public class FieldInfoTest extends TestCase { public void test_null() throws Exception { - FieldInfo fieldInfo = new FieldInfo("getValue", Entity.class.getMethod("getValue"), null, null, null, 0, 0, null, null, null); + FieldInfo fieldInfo = new FieldInfo("getValue", Entity.class.getMethod("getValue"), null, null, null, 0, 0, 0, null, null, null); Assert.assertEquals(null, fieldInfo.getAnnotation()); Field field = GenericFieldEntity.class.getField("value"); Type type = new ParameterizedTypeImpl(new Type[] { ValueObject.class }, null, GenericFieldEntity.class); - FieldInfo fieldInfoOfField = new FieldInfo("value", null, field, GenericFieldEntity.class, type, 0, 0, null, null, null); + FieldInfo fieldInfoOfField = new FieldInfo("value", null, field, GenericFieldEntity.class, type, 0, 0, 0, null, null, null); Assert.assertEquals(fieldInfoOfField.fieldType, ValueObject.class); Assert.assertEquals(fieldInfoOfField.fieldClass, ValueObject.class); field = GenericListFieldEntity.class.getField("value"); type = new ParameterizedTypeImpl(new Type[] { ValueObject.class }, null, GenericListFieldEntity.class); - FieldInfo fieldInfoOfListField = new FieldInfo("value", null, field, GenericListFieldEntity.class, type, 0, 0, null, null, null); + FieldInfo fieldInfoOfListField = new FieldInfo("value", null, field, GenericListFieldEntity.class, type, 0, 0, 0, null, null, null); ParameterizedTypeImpl actualFieldType = (ParameterizedTypeImpl) fieldInfoOfListField.fieldType; Assert.assertEquals(actualFieldType.getActualTypeArguments()[0], ValueObject.class); Assert.assertEquals(actualFieldType.getRawType(), List.class); @@ -34,7 +34,7 @@ public void test_null() throws Exception { Method method = GenericSetterEntity.class.getMethod("setValue", Object.class); type = new ParameterizedTypeImpl(new Type[] { ValueObject.class }, null, GenericSetterEntity.class); - FieldInfo fieldInfoOfSetter = new FieldInfo("value", method, null, GenericSetterEntity.class, type, 0, 0, null, null, null); + FieldInfo fieldInfoOfSetter = new FieldInfo("value", method, null, GenericSetterEntity.class, type, 0, 0, 0, null, null, null); Assert.assertEquals(fieldInfoOfSetter.fieldType, ValueObject.class); Assert.assertEquals(fieldInfoOfSetter.fieldClass, ValueObject.class); @@ -42,7 +42,7 @@ public void test_null() throws Exception { method = GenericListSetterEntity.class.getMethod("setValue", List.class); type = new ParameterizedTypeImpl(new Type[] { ValueObject.class }, null, GenericListSetterEntity.class); - FieldInfo fieldInfoOfListSetter = new FieldInfo("value", method, null, GenericListSetterEntity.class, type, 0, 0, null, null, null); + FieldInfo fieldInfoOfListSetter = new FieldInfo("value", method, null, GenericListSetterEntity.class, type, 0, 0, 0, null, null, null); Assert.assertEquals(actualFieldType.getActualTypeArguments()[0], ValueObject.class); Assert.assertEquals(actualFieldType.getRawType(), List.class); Assert.assertEquals(fieldInfoOfListSetter.fieldClass, List.class); diff --git a/src/test/java/com/alibaba/json/test/codegen/DepartmentCodec.java b/src/test/java/com/alibaba/json/test/codegen/DepartmentCodec.java index 704db6cf4c..6a8d9dc726 100644 --- a/src/test/java/com/alibaba/json/test/codegen/DepartmentCodec.java +++ b/src/test/java/com/alibaba/json/test/codegen/DepartmentCodec.java @@ -210,7 +210,7 @@ public Object deserialze(DefaultJSONParser parser, Type type, Object fieldName) } if (restFlag) { - return super.parseRest(parser, type, fieldName, instance); + return super.parseRest(parser, type, fieldName, instance, 0); } return instance; diff --git a/src/test/java/data/media/ImageGenDecoder.java b/src/test/java/data/media/ImageGenDecoder.java index fb3ad5e127..0a29137882 100644 --- a/src/test/java/data/media/ImageGenDecoder.java +++ b/src/test/java/data/media/ImageGenDecoder.java @@ -171,7 +171,7 @@ public Object deserialze(DefaultJSONParser parser, Type type, Object fieldName) } if (restFlag) { - return super.parseRest(parser, type, fieldName, instance); + return super.parseRest(parser, type, fieldName, instance, 0); } return instance; diff --git a/src/test/java/data/media/MediaContentGenDecoder.java b/src/test/java/data/media/MediaContentGenDecoder.java index bc012d8c62..038f34cd22 100644 --- a/src/test/java/data/media/MediaContentGenDecoder.java +++ b/src/test/java/data/media/MediaContentGenDecoder.java @@ -153,7 +153,7 @@ public Object deserialze(DefaultJSONParser parser, Type type, Object fieldName) } if (restFlag) { - return super.parseRest(parser, type, fieldName, instance); + return super.parseRest(parser, type, fieldName, instance, 0); } return instance; diff --git a/src/test/java/data/media/MediaGenDecoder.java b/src/test/java/data/media/MediaGenDecoder.java index 0a4a5a4642..e59b038157 100644 --- a/src/test/java/data/media/MediaGenDecoder.java +++ b/src/test/java/data/media/MediaGenDecoder.java @@ -307,7 +307,7 @@ public Object deserialze(DefaultJSONParser parser, Type type, Object fieldName) } if (restFlag) { - return super.parseRest(parser, type, fieldName, instance); + return super.parseRest(parser, type, fieldName, instance, 0); } return instance;