improved for BeanToArray

This commit is contained in:
wenshao
2014-10-04 17:37:40 +08:00
parent 895bc331ca
commit 92f7a91f93
11 changed files with 147 additions and 24 deletions
@@ -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;
@@ -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;
}
}
@@ -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");
@@ -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)
@@ -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<FieldDeserializer> getSortedFieldDeserializers() {
return sortedFieldDeserializers;
}
public final boolean isSupportArrayToBean(JSONLexer lexer) {
return Feature.isEnabled(beanInfo.getParserFeatures(), Feature.SupportArrayToBean) || lexer.isEnabled(Feature.SupportArrayToBean);
}
}
@@ -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_);
// /////
@@ -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;
}
}
@@ -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;
}
}
@@ -30,9 +30,12 @@ public class DeserializeBeanInfo {
private final List<FieldInfo> fieldList = new ArrayList<FieldInfo>();
private final List<FieldInfo> sortedFieldList = new ArrayList<FieldInfo>();
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;
}
}
@@ -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;
@@ -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;
}
}
}