From 060a29e1c176855cf5b2a59a2deb302aa0945837 Mon Sep 17 00:00:00 2001 From: wenshao Date: Sun, 23 Jun 2013 19:18:08 +0800 Subject: [PATCH] bug fixed for custom fieldName --- .../serializer/ASMSerializerFactory.java | 2 +- .../fastjson/util/DeserializeBeanInfo.java | 9 +- .../com/alibaba/fastjson/util/TypeUtils.java | 2161 ++++++++--------- .../json/bvt/bug/KeyBug_for_zhongl.java | 62 + 4 files changed, 1145 insertions(+), 1089 deletions(-) create mode 100644 src/test/java/com/alibaba/json/bvt/bug/KeyBug_for_zhongl.java diff --git a/src/main/java/com/alibaba/fastjson/serializer/ASMSerializerFactory.java b/src/main/java/com/alibaba/fastjson/serializer/ASMSerializerFactory.java index 83743e707..8992693ef 100755 --- a/src/main/java/com/alibaba/fastjson/serializer/ASMSerializerFactory.java +++ b/src/main/java/com/alibaba/fastjson/serializer/ASMSerializerFactory.java @@ -639,7 +639,7 @@ public class ASMSerializerFactory implements Opcodes { mw.visitMethodInsn(INVOKEVIRTUAL, getType(method.getDeclaringClass()), method.getName(), getDesc(method)); } else { mw.visitVarInsn(ALOAD, context.var("entity")); - mw.visitFieldInsn(GETFIELD, getType(property.getDeclaringClass()), property.getName(), + mw.visitFieldInsn(GETFIELD, getType(property.getDeclaringClass()), property.getField().getName(), getDesc(property.getFieldClass())); } } diff --git a/src/main/java/com/alibaba/fastjson/util/DeserializeBeanInfo.java b/src/main/java/com/alibaba/fastjson/util/DeserializeBeanInfo.java index fc8e22383..7239865b7 100755 --- a/src/main/java/com/alibaba/fastjson/util/DeserializeBeanInfo.java +++ b/src/main/java/com/alibaba/fastjson/util/DeserializeBeanInfo.java @@ -240,7 +240,14 @@ public class DeserializeBeanInfo { continue; } - beanInfo.add(new FieldInfo(field.getName(), null, field, clazz, type)); + String propertyName = field.getName(); + + JSONField fieldAnnotation = field.getAnnotation(JSONField.class); + + if (fieldAnnotation != null && fieldAnnotation.name().length() != 0) { + propertyName = fieldAnnotation.name(); + } + beanInfo.add(new FieldInfo(propertyName, null, field, clazz, type)); } for (Method method : clazz.getMethods()) { diff --git a/src/main/java/com/alibaba/fastjson/util/TypeUtils.java b/src/main/java/com/alibaba/fastjson/util/TypeUtils.java index 24c3e733d..10a2b3fd4 100755 --- a/src/main/java/com/alibaba/fastjson/util/TypeUtils.java +++ b/src/main/java/com/alibaba/fastjson/util/TypeUtils.java @@ -54,1091 +54,1078 @@ import com.alibaba.fastjson.parser.deserializer.FieldDeserializer; */ public class TypeUtils { - public static final String castToString(Object value) { - if (value == null) { - return null; - } - - return value.toString(); - } - - public static final Byte castToByte(Object value) { - if (value == null) { - return null; - } - - if (value instanceof Number) { - return ((Number) value).byteValue(); - } - - if (value instanceof String) { - String strVal = (String) value; - if (strVal.length() == 0) { - return null; - } - return Byte.parseByte(strVal); - } - - throw new JSONException("can not cast to byte, value : " + value); - } - - public static final Character castToChar(Object value) { - if (value == null) { - return null; - } - - if (value instanceof Character) { - return (Character) value; - } - - if (value instanceof String) { - String strVal = (String) value; - - if (strVal.length() == 0) { - return null; - } - - if (strVal.length() != 1) { - throw new JSONException("can not cast to byte, value : " - + value); - } - - return strVal.charAt(0); - } - - throw new JSONException("can not cast to byte, value : " + value); - } - - public static final Short castToShort(Object value) { - if (value == null) { - return null; - } - - if (value instanceof Number) { - return ((Number) value).shortValue(); - } - - if (value instanceof String) { - String strVal = (String) value; - if (strVal.length() == 0) { - return null; - } - return Short.parseShort(strVal); - } - - throw new JSONException("can not cast to short, value : " + value); - } - - public static final BigDecimal castToBigDecimal(Object value) { - if (value == null) { - return null; - } - - if (value instanceof BigDecimal) { - return (BigDecimal) value; - } - - if (value instanceof BigInteger) { - return new BigDecimal((BigInteger) value); - } - - String strVal = value.toString(); - if (strVal.length() == 0) { - return null; - } - - return new BigDecimal(strVal); - } - - public static final BigInteger castToBigInteger(Object value) { - if (value == null) { - return null; - } - - if (value instanceof BigInteger) { - return (BigInteger) value; - } - - if (value instanceof Float || value instanceof Double) { - return BigInteger.valueOf(((Number) value).longValue()); - } - - String strVal = value.toString(); - if (strVal.length() == 0) { - return null; - } - - return new BigInteger(strVal); - } - - public static final Float castToFloat(Object value) { - if (value == null) { - return null; - } - - if (value instanceof Number) { - return ((Number) value).floatValue(); - } - - if (value instanceof String) { - String strVal = value.toString(); - if (strVal.length() == 0) { - return null; - } - - return Float.parseFloat(strVal); - } - - throw new JSONException("can not cast to float, value : " + value); - } - - public static final Double castToDouble(Object value) { - if (value == null) { - return null; - } - - if (value instanceof Number) { - return ((Number) value).doubleValue(); - } - - if (value instanceof String) { - String strVal = value.toString(); - if (strVal.length() == 0) { - return null; - } - return Double.parseDouble(strVal); - } - - throw new JSONException("can not cast to double, value : " + value); - } - - public static final Date castToDate(Object value) { - if (value == null) { - return null; - } - - if (value instanceof Calendar) { - return ((Calendar) value).getTime(); - } - - if (value instanceof Date) { - return (Date) value; - } - - long longValue = 0; - - if (value instanceof Number) { - longValue = ((Number) value).longValue(); - } - - if (value instanceof String) { - String strVal = (String) value; - - if (strVal.indexOf('-') != -1) { - String format; - if (strVal.length() == JSON.DEFFAULT_DATE_FORMAT.length()) { - format = JSON.DEFFAULT_DATE_FORMAT; - } else if (strVal.length() == 10) { - format = "yyyy-MM-dd"; - } else if (strVal.length() == "yyyy-MM-dd HH:mm:ss".length()) { - format = "yyyy-MM-dd HH:mm:ss"; - } else { - format = "yyyy-MM-dd HH:mm:ss.SSS"; - } - - SimpleDateFormat dateFormat = new SimpleDateFormat(format); - try { - return (Date) dateFormat.parse(strVal); - } catch (ParseException e) { - throw new JSONException("can not cast to Date, value : " - + strVal); - } - } - - if (strVal.length() == 0) { - return null; - } - - longValue = Long.parseLong(strVal); - } - - if (longValue <= 0) { - throw new JSONException("can not cast to Date, value : " + value); - } - - return new Date(longValue); - } - - public static final java.sql.Date castToSqlDate(Object value) { - if (value == null) { - return null; - } - - if (value instanceof Calendar) { - return new java.sql.Date(((Calendar) value).getTimeInMillis()); - } - - if (value instanceof java.sql.Date) { - return (java.sql.Date) value; - } - - if (value instanceof java.util.Date) { - return new java.sql.Date(((java.util.Date) value).getTime()); - } - - long longValue = 0; - - if (value instanceof Number) { - longValue = ((Number) value).longValue(); - } - - if (value instanceof String) { - String strVal = (String) value; - if (strVal.length() == 0) { - return null; - } - - longValue = Long.parseLong(strVal); - } - - if (longValue <= 0) { - throw new JSONException("can not cast to Date, value : " + value); - } - - return new java.sql.Date(longValue); - } - - public static final java.sql.Timestamp castToTimestamp(Object value) { - if (value == null) { - return null; - } - - if (value instanceof Calendar) { - return new java.sql.Timestamp(((Calendar) value).getTimeInMillis()); - } - - if (value instanceof java.sql.Timestamp) { - return (java.sql.Timestamp) value; - } - - if (value instanceof java.util.Date) { - return new java.sql.Timestamp(((java.util.Date) value).getTime()); - } - - long longValue = 0; - - if (value instanceof Number) { - longValue = ((Number) value).longValue(); - } - - if (value instanceof String) { - String strVal = (String) value; - if (strVal.length() == 0) { - return null; - } - - longValue = Long.parseLong(strVal); - } - - if (longValue <= 0) { - throw new JSONException("can not cast to Date, value : " + value); - } - - return new java.sql.Timestamp(longValue); - } - - public static final Long castToLong(Object value) { - if (value == null) { - return null; - } - - if (value instanceof Number) { - return ((Number) value).longValue(); - } - - if (value instanceof String) { - String strVal = (String) value; - if (strVal.length() == 0) { - return null; - } - - return Long.parseLong(strVal); - } - - throw new JSONException("can not cast to long, value : " + value); - } - - public static final Integer castToInt(Object value) { - if (value == null) { - return null; - } - - if (value instanceof Integer) { - return (Integer) value; - } - - if (value instanceof Number) { - return ((Number) value).intValue(); - } - - if (value instanceof String) { - String strVal = (String) value; - if (strVal.length() == 0) { - return null; - } - - return Integer.parseInt(strVal); - } - - throw new JSONException("can not cast to int, value : " + value); - } - - public static final byte[] castToBytes(Object value) { - if (value instanceof byte[]) { - return (byte[]) value; - } - - if (value instanceof String) { - return Base64.decodeFast((String) value); - } - throw new JSONException("can not cast to int, value : " + value); - } - - public static final Boolean castToBoolean(Object value) { - if (value == null) { - return null; - } - - if (value instanceof Boolean) { - return (Boolean) value; - } - - if (value instanceof Number) { - return ((Number) value).intValue() == 1; - } - - if (value instanceof String) { - String str = (String) value; - if (str.length() == 0) { - return null; - } - - if ("true".equals(str)) { - return Boolean.TRUE; - } - if ("false".equals(str)) { - return Boolean.FALSE; - } - - if ("1".equals(str)) { - return Boolean.TRUE; - } - } - - throw new JSONException("can not cast to int, value : " + value); - } - - public static final T castToJavaBean(Object obj, Class clazz) { - return cast(obj, clazz, ParserConfig.getGlobalInstance()); - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - public static final T cast(Object obj, Class clazz, - ParserConfig mapping) { - if (obj == null) { - return null; - } - - if (clazz == null) { - throw new IllegalArgumentException("clazz is null"); - } - - if (clazz == obj.getClass()) { - return (T) obj; - } - - if (obj instanceof Map) { - if (clazz == Map.class) { - return (T) obj; - } - - return castToJavaBean((Map) obj, clazz, mapping); - } - - if (clazz.isArray()) { - if (obj instanceof Collection) { - - Collection collection = (Collection) obj; - int index = 0; - Object array = Array.newInstance(clazz.getComponentType(), - collection.size()); - for (Object item : collection) { - Object value = cast(item, clazz.getComponentType(), mapping); - Array.set(array, index, value); - index++; - } - - return (T) array; - } - } - - if (clazz.isAssignableFrom(obj.getClass())) { - return (T) obj; - } - - if (clazz == boolean.class || clazz == Boolean.class) { - return (T) castToBoolean(obj); - } - - if (clazz == byte.class || clazz == Byte.class) { - return (T) castToByte(obj); - } - - // if (clazz == char.class || clazz == Character.class) { - // return (T) castToCharacter(obj); - // } - - if (clazz == short.class || clazz == Short.class) { - return (T) castToShort(obj); - } - - if (clazz == int.class || clazz == Integer.class) { - return (T) castToInt(obj); - } - - if (clazz == long.class || clazz == Long.class) { - return (T) castToLong(obj); - } - - if (clazz == float.class || clazz == Float.class) { - return (T) castToFloat(obj); - } - - if (clazz == double.class || clazz == Double.class) { - return (T) castToDouble(obj); - } - - if (clazz == String.class) { - return (T) castToString(obj); - } - - if (clazz == BigDecimal.class) { - return (T) castToBigDecimal(obj); - } - - if (clazz == BigInteger.class) { - return (T) castToBigInteger(obj); - } - - if (clazz == Date.class) { - return (T) castToDate(obj); - } - - if (clazz == java.sql.Date.class) { - return (T) castToSqlDate(obj); - } - - if (clazz == java.sql.Timestamp.class) { - return (T) castToTimestamp(obj); - } - - if (clazz.isEnum()) { - return (T) castToEnum(obj, clazz, mapping); - } - - if (Calendar.class.isAssignableFrom(clazz)) { - Date date = castToDate(obj); - Calendar calendar; - if (clazz == Calendar.class) { - calendar = Calendar.getInstance(); - } else { - try { - calendar = (Calendar) clazz.newInstance(); - } catch (Exception e) { - throw new JSONException("can not cast to : " - + clazz.getName(), e); - } - } - calendar.setTime(date); - return (T) calendar; - } - - if (obj instanceof String) { - String strVal = (String) obj; - if (strVal.length() == 0) { - return null; - } - } - - throw new JSONException("can not cast to : " + clazz.getName()); - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - public static final T castToEnum(Object obj, Class clazz, - ParserConfig mapping) { - try { - if (obj instanceof String) { - String name = (String) obj; - if (name.length() == 0) { - return null; - } - - return (T) Enum.valueOf((Class) clazz, name); - } - - if (obj instanceof Number) { - int ordinal = ((Number) obj).intValue(); - - Method method = clazz.getMethod("values"); - Object[] values = (Object[]) method.invoke(null); - for (Object value : values) { - Enum e = (Enum) value; - if (e.ordinal() == ordinal) { - return (T) e; - } - } - } - } catch (Exception ex) { - throw new JSONException("can not cast to : " + clazz.getName(), ex); - } - - throw new JSONException("can not cast to : " + clazz.getName()); - } - - @SuppressWarnings("unchecked") - public static final T cast(Object obj, Type type, ParserConfig mapping) { - if (obj == null) { - return null; - } - - if (type instanceof Class) { - return (T) cast(obj, (Class) type, mapping); - } - - if (type instanceof ParameterizedType) { - return (T) cast(obj, (ParameterizedType) type, mapping); - } - - if (obj instanceof String) { - String strVal = (String) obj; - if (strVal.length() == 0) { - return null; - } - } - - if (type instanceof TypeVariable) { - return (T) obj; - } - - throw new JSONException("can not cast to : " + type); - } - - @SuppressWarnings({ "rawtypes", "unchecked" }) - public static final T cast(Object obj, ParameterizedType type, - ParserConfig mapping) { - Type rawTye = type.getRawType(); - - if (rawTye == List.class || rawTye == ArrayList.class) { - Type itemType = type.getActualTypeArguments()[0]; - - if (obj instanceof Iterable) { - List list = new ArrayList(); - - for (Iterator it = ((Iterable) obj).iterator(); it.hasNext();) { - Object item = it.next(); - list.add(cast(item, itemType, mapping)); - } - - return (T) list; - } - } - - if (rawTye == Map.class || rawTye == HashMap.class) { - Type keyType = type.getActualTypeArguments()[0]; - Type valueType = type.getActualTypeArguments()[1]; - - if (obj instanceof Map) { - Map map = new HashMap(); - - for (Map.Entry entry : ((Map) obj).entrySet()) { - Object key = cast(entry.getKey(), keyType, mapping); - Object value = cast(entry.getValue(), valueType, mapping); - - map.put(key, value); - } - - return (T) map; - } - } - - if (obj instanceof String) { - String strVal = (String) obj; - if (strVal.length() == 0) { - return null; - } - } - - if (type.getActualTypeArguments().length == 1) { - Type argType = type.getActualTypeArguments()[0]; - if (argType instanceof WildcardType) { - return (T) cast(obj, rawTye, mapping); - } - } - - throw new JSONException("can not cast to : " + type); - } - - @SuppressWarnings({ "unchecked" }) - public static final T castToJavaBean(Map map, - Class clazz, ParserConfig mapping) { - try { - if (clazz == StackTraceElement.class) { - String declaringClass = (String) map.get("className"); - String methodName = (String) map.get("methodName"); - String fileName = (String) map.get("fileName"); - int lineNumber; - { - Number value = (Number) map.get("lineNumber"); - if (value == null) { - lineNumber = 0; - } else { - lineNumber = value.intValue(); - } - } - - return (T) new StackTraceElement(declaringClass, methodName, - fileName, lineNumber); - } - - { - Object iClassObject = map.get(JSON.DEFAULT_TYPE_KEY); - if (iClassObject instanceof String) { - String className = (String) iClassObject; - - clazz = (Class) loadClass(className); - - if (clazz == null) { - throw new ClassNotFoundException(className - + " not found"); - } - } - } - - if (clazz.isInterface()) { - JSONObject object; - - if (map instanceof JSONObject) { - object = (JSONObject) map; - } else { - object = new JSONObject(map); - } - - return (T) Proxy.newProxyInstance(Thread.currentThread() - .getContextClassLoader(), new Class[] { clazz }, - object); - } - - Map setters = mapping - .getFieldDeserializers(clazz); - - T object = clazz.newInstance(); - - for (Map.Entry entry : setters - .entrySet()) { - String key = entry.getKey(); - Method method = entry.getValue().getMethod(); - - if (map.containsKey(key)) { - Object value = map.get(key); - value = cast(value, method.getGenericParameterTypes()[0], - mapping); - method.invoke(object, new Object[] { value }); - } - } - - return object; - } catch (Exception e) { - throw new JSONException(e.getMessage(), e); - } - } - - private static ConcurrentMap> mappings = new ConcurrentHashMap>(); - static { - addBaseClassMappings(); - } - - public static void addClassMapping(String className, Class clazz) { - if (className == null) { - className = clazz.getName(); - } - - mappings.put(className, clazz); - } - - public static void addBaseClassMappings() { - mappings.put("byte", byte.class); - mappings.put("short", short.class); - mappings.put("int", int.class); - mappings.put("long", long.class); - mappings.put("float", float.class); - mappings.put("double", double.class); - mappings.put("boolean", boolean.class); - mappings.put("char", char.class); - - mappings.put("[byte", byte[].class); - mappings.put("[short", short[].class); - mappings.put("[int", int[].class); - mappings.put("[long", long[].class); - mappings.put("[float", float[].class); - mappings.put("[double", double[].class); - mappings.put("[boolean", boolean[].class); - mappings.put("[char", char[].class); - - mappings.put(HashMap.class.getName(), HashMap.class); - } - - public static void clearClassMapping() { - mappings.clear(); - addBaseClassMappings(); - } - - public static Class loadClass(String className) { - if (className == null || className.length() == 0) { - return null; - } - - Class clazz = mappings.get(className); - - if (clazz != null) { - return clazz; - } - - if (className.charAt(0) == '[') { - Class componentType = loadClass(className.substring(1)); - return Array.newInstance(componentType, 0).getClass(); - } - - if (className.startsWith("L") && className.endsWith(";")) { - String newClassName = className - .substring(1, className.length() - 1); - return loadClass(newClassName); - } - - try { - clazz = Thread.currentThread().getContextClassLoader() - .loadClass(className); - - addClassMapping(className, clazz); - - return clazz; - } catch (Throwable e) { - // skip - } - - try { - clazz = Class.forName(className); - - addClassMapping(className, clazz); - - return clazz; - } catch (Throwable e) { - // skip - } - - return clazz; - } - - public static List computeGetters(Class clazz, - Map aliasMap) { - return computeGetters(clazz, aliasMap, true); - } - - public static List computeGetters(Class clazz, - Map aliasMap, boolean sorted) { - Map fieldInfoMap = new LinkedHashMap(); - - for (Method method : clazz.getMethods()) { - String methodName = method.getName(); - - if (Modifier.isStatic(method.getModifiers())) { - continue; - } - - if (method.getReturnType().equals(Void.TYPE)) { - continue; - } - - if (method.getParameterTypes().length != 0) { - continue; - } - - if (method.getReturnType() == ClassLoader.class) { - continue; - } - - if (method.getName().equals("getMetaClass") - && method.getReturnType().getName() - .equals("groovy.lang.MetaClass")) { - continue; - } - - JSONField annotation = method.getAnnotation(JSONField.class); - - if (annotation == null) { - annotation = getSupperMethodAnnotation(clazz, method); - } - - if (annotation != null) { - if (!annotation.serialize()) { - continue; - } - - if (annotation.name().length() != 0) { - String propertyName = annotation.name(); - - if (aliasMap != null) { - propertyName = aliasMap.get(propertyName); - if (propertyName == null) { - continue; - } - } - - fieldInfoMap.put(propertyName, new FieldInfo(propertyName, - method, null)); - continue; - } - } - - if (methodName.startsWith("get")) { - if (methodName.length() < 4) { - continue; - } - - if (methodName.equals("getClass")) { - continue; - } - - if (!Character.isUpperCase(methodName.charAt(3))) { - continue; - } - - String propertyName = Character.toLowerCase(methodName - .charAt(3)) + methodName.substring(4); - - boolean ignore = isJSONTypeIgnore(clazz, propertyName); - - if (ignore) { - continue; - } - - Field field = ParserConfig.getField(clazz, propertyName); - if (field == null) { - field = ParserConfig.getField(clazz, - methodName.substring(3)); - } - - if (field != null) { - JSONField fieldAnnotation = field - .getAnnotation(JSONField.class); - - if (fieldAnnotation != null) { - if (!fieldAnnotation.serialize()) { - continue; - } - - if (fieldAnnotation.name().length() != 0) { - propertyName = fieldAnnotation.name(); - - if (aliasMap != null) { - propertyName = aliasMap.get(propertyName); - if (propertyName == null) { - continue; - } - } - } - } - } - - if (aliasMap != null) { - propertyName = aliasMap.get(propertyName); - if (propertyName == null) { - continue; - } - } - - fieldInfoMap.put(propertyName, new FieldInfo(propertyName, - method, field)); - } - - if (methodName.startsWith("is")) { - if (methodName.length() < 3) { - continue; - } - - if (!Character.isUpperCase(methodName.charAt(2))) { - continue; - } - - String propertyName = Character.toLowerCase(methodName - .charAt(2)) + methodName.substring(3); - - Field field = ParserConfig.getField(clazz, propertyName); - if (field != null) { - JSONField fieldAnnotation = field - .getAnnotation(JSONField.class); - - if (fieldAnnotation != null) { - if (!fieldAnnotation.serialize()) { - continue; - } - - if (fieldAnnotation.name().length() != 0) { - propertyName = fieldAnnotation.name(); - - if (aliasMap != null) { - propertyName = aliasMap.get(propertyName); - if (propertyName == null) { - continue; - } - } - } - } - } - - if (aliasMap != null) { - propertyName = aliasMap.get(propertyName); - if (propertyName == null) { - continue; - } - } - - fieldInfoMap.put(propertyName, new FieldInfo(propertyName, - method, field)); - } - } - - for (Field field : clazz.getFields()) { - if (Modifier.isStatic(field.getModifiers())) { - continue; - } - - if (!Modifier.isPublic(field.getModifiers())) { - continue; - } - - if (!fieldInfoMap.containsKey(field.getName())) { - fieldInfoMap.put(field.getName(), new FieldInfo( - field.getName(), null, field)); - } - } - - List fieldInfoList = new ArrayList(); - - boolean containsAll = false; - String[] orders = null; - - JSONType annotation = clazz.getAnnotation(JSONType.class); - if (annotation != null) { - orders = annotation.orders(); - - if (orders != null && orders.length == fieldInfoMap.size()) { - containsAll = true; - for (String item : orders) { - if (!fieldInfoMap.containsKey(item)) { - containsAll = false; - break; - } - } - } else { - containsAll = false; - } - } - - if (containsAll) { - for (String item : orders) { - FieldInfo fieldInfo = fieldInfoMap.get(item); - fieldInfoList.add(fieldInfo); - } - } else { - for (FieldInfo fieldInfo : fieldInfoMap.values()) { - fieldInfoList.add(fieldInfo); - } - - if (sorted) { - Collections.sort(fieldInfoList); - } - } - - return fieldInfoList; - } - - public static JSONField getSupperMethodAnnotation(Class clazz, - Method method) { - for (Class interfaceClass : clazz.getInterfaces()) { - for (Method interfaceMethod : interfaceClass.getMethods()) { - if (!interfaceMethod.getName().equals(method.getName())) { - continue; - } - - if (interfaceMethod.getParameterTypes().length != method - .getParameterTypes().length) { - continue; - } - - boolean match = true; - for (int i = 0; i < interfaceMethod.getParameterTypes().length; ++i) { - if (!interfaceMethod.getParameterTypes()[i].equals(method - .getParameterTypes()[i])) { - match = false; - break; - } - } - - if (!match) { - continue; - } - - JSONField annotation = interfaceMethod - .getAnnotation(JSONField.class); - if (annotation != null) { - return annotation; - } - } - } - - return null; - } - - private static boolean isJSONTypeIgnore(Class clazz, String propertyName) { - JSONType jsonType = clazz.getAnnotation(JSONType.class); - - if (jsonType != null && jsonType.ignores() != null) { - for (String item : jsonType.ignores()) { - if (propertyName.equalsIgnoreCase(item)) { - return true; - } - } - } - - if (clazz.getSuperclass() != Object.class - && clazz.getSuperclass() != null) { - if (isJSONTypeIgnore(clazz.getSuperclass(), propertyName)) { - return true; - } - } - - return false; - } - - public static Class getClass(Type type) { - if (type.getClass() == Class.class) { - return (Class) type; - } - - if (type instanceof ParameterizedType) { - return getClass(((ParameterizedType) type).getRawType()); - } - - return Object.class; - } + public static final String castToString(Object value) { + if (value == null) { + return null; + } + + return value.toString(); + } + + public static final Byte castToByte(Object value) { + if (value == null) { + return null; + } + + if (value instanceof Number) { + return ((Number) value).byteValue(); + } + + if (value instanceof String) { + String strVal = (String) value; + if (strVal.length() == 0) { + return null; + } + return Byte.parseByte(strVal); + } + + throw new JSONException("can not cast to byte, value : " + value); + } + + public static final Character castToChar(Object value) { + if (value == null) { + return null; + } + + if (value instanceof Character) { + return (Character) value; + } + + if (value instanceof String) { + String strVal = (String) value; + + if (strVal.length() == 0) { + return null; + } + + if (strVal.length() != 1) { + throw new JSONException("can not cast to byte, value : " + value); + } + + return strVal.charAt(0); + } + + throw new JSONException("can not cast to byte, value : " + value); + } + + public static final Short castToShort(Object value) { + if (value == null) { + return null; + } + + if (value instanceof Number) { + return ((Number) value).shortValue(); + } + + if (value instanceof String) { + String strVal = (String) value; + if (strVal.length() == 0) { + return null; + } + return Short.parseShort(strVal); + } + + throw new JSONException("can not cast to short, value : " + value); + } + + public static final BigDecimal castToBigDecimal(Object value) { + if (value == null) { + return null; + } + + if (value instanceof BigDecimal) { + return (BigDecimal) value; + } + + if (value instanceof BigInteger) { + return new BigDecimal((BigInteger) value); + } + + String strVal = value.toString(); + if (strVal.length() == 0) { + return null; + } + + return new BigDecimal(strVal); + } + + public static final BigInteger castToBigInteger(Object value) { + if (value == null) { + return null; + } + + if (value instanceof BigInteger) { + return (BigInteger) value; + } + + if (value instanceof Float || value instanceof Double) { + return BigInteger.valueOf(((Number) value).longValue()); + } + + String strVal = value.toString(); + if (strVal.length() == 0) { + return null; + } + + return new BigInteger(strVal); + } + + public static final Float castToFloat(Object value) { + if (value == null) { + return null; + } + + if (value instanceof Number) { + return ((Number) value).floatValue(); + } + + if (value instanceof String) { + String strVal = value.toString(); + if (strVal.length() == 0) { + return null; + } + + return Float.parseFloat(strVal); + } + + throw new JSONException("can not cast to float, value : " + value); + } + + public static final Double castToDouble(Object value) { + if (value == null) { + return null; + } + + if (value instanceof Number) { + return ((Number) value).doubleValue(); + } + + if (value instanceof String) { + String strVal = value.toString(); + if (strVal.length() == 0) { + return null; + } + return Double.parseDouble(strVal); + } + + throw new JSONException("can not cast to double, value : " + value); + } + + public static final Date castToDate(Object value) { + if (value == null) { + return null; + } + + if (value instanceof Calendar) { + return ((Calendar) value).getTime(); + } + + if (value instanceof Date) { + return (Date) value; + } + + long longValue = 0; + + if (value instanceof Number) { + longValue = ((Number) value).longValue(); + } + + if (value instanceof String) { + String strVal = (String) value; + + if (strVal.indexOf('-') != -1) { + String format; + if (strVal.length() == JSON.DEFFAULT_DATE_FORMAT.length()) { + format = JSON.DEFFAULT_DATE_FORMAT; + } else if (strVal.length() == 10) { + format = "yyyy-MM-dd"; + } else if (strVal.length() == "yyyy-MM-dd HH:mm:ss".length()) { + format = "yyyy-MM-dd HH:mm:ss"; + } else { + format = "yyyy-MM-dd HH:mm:ss.SSS"; + } + + SimpleDateFormat dateFormat = new SimpleDateFormat(format); + try { + return (Date) dateFormat.parse(strVal); + } catch (ParseException e) { + throw new JSONException("can not cast to Date, value : " + strVal); + } + } + + if (strVal.length() == 0) { + return null; + } + + longValue = Long.parseLong(strVal); + } + + if (longValue <= 0) { + throw new JSONException("can not cast to Date, value : " + value); + } + + return new Date(longValue); + } + + public static final java.sql.Date castToSqlDate(Object value) { + if (value == null) { + return null; + } + + if (value instanceof Calendar) { + return new java.sql.Date(((Calendar) value).getTimeInMillis()); + } + + if (value instanceof java.sql.Date) { + return (java.sql.Date) value; + } + + if (value instanceof java.util.Date) { + return new java.sql.Date(((java.util.Date) value).getTime()); + } + + long longValue = 0; + + if (value instanceof Number) { + longValue = ((Number) value).longValue(); + } + + if (value instanceof String) { + String strVal = (String) value; + if (strVal.length() == 0) { + return null; + } + + longValue = Long.parseLong(strVal); + } + + if (longValue <= 0) { + throw new JSONException("can not cast to Date, value : " + value); + } + + return new java.sql.Date(longValue); + } + + public static final java.sql.Timestamp castToTimestamp(Object value) { + if (value == null) { + return null; + } + + if (value instanceof Calendar) { + return new java.sql.Timestamp(((Calendar) value).getTimeInMillis()); + } + + if (value instanceof java.sql.Timestamp) { + return (java.sql.Timestamp) value; + } + + if (value instanceof java.util.Date) { + return new java.sql.Timestamp(((java.util.Date) value).getTime()); + } + + long longValue = 0; + + if (value instanceof Number) { + longValue = ((Number) value).longValue(); + } + + if (value instanceof String) { + String strVal = (String) value; + if (strVal.length() == 0) { + return null; + } + + longValue = Long.parseLong(strVal); + } + + if (longValue <= 0) { + throw new JSONException("can not cast to Date, value : " + value); + } + + return new java.sql.Timestamp(longValue); + } + + public static final Long castToLong(Object value) { + if (value == null) { + return null; + } + + if (value instanceof Number) { + return ((Number) value).longValue(); + } + + if (value instanceof String) { + String strVal = (String) value; + if (strVal.length() == 0) { + return null; + } + + return Long.parseLong(strVal); + } + + throw new JSONException("can not cast to long, value : " + value); + } + + public static final Integer castToInt(Object value) { + if (value == null) { + return null; + } + + if (value instanceof Integer) { + return (Integer) value; + } + + if (value instanceof Number) { + return ((Number) value).intValue(); + } + + if (value instanceof String) { + String strVal = (String) value; + if (strVal.length() == 0) { + return null; + } + + return Integer.parseInt(strVal); + } + + throw new JSONException("can not cast to int, value : " + value); + } + + public static final byte[] castToBytes(Object value) { + if (value instanceof byte[]) { + return (byte[]) value; + } + + if (value instanceof String) { + return Base64.decodeFast((String) value); + } + throw new JSONException("can not cast to int, value : " + value); + } + + public static final Boolean castToBoolean(Object value) { + if (value == null) { + return null; + } + + if (value instanceof Boolean) { + return (Boolean) value; + } + + if (value instanceof Number) { + return ((Number) value).intValue() == 1; + } + + if (value instanceof String) { + String str = (String) value; + if (str.length() == 0) { + return null; + } + + if ("true".equals(str)) { + return Boolean.TRUE; + } + if ("false".equals(str)) { + return Boolean.FALSE; + } + + if ("1".equals(str)) { + return Boolean.TRUE; + } + } + + throw new JSONException("can not cast to int, value : " + value); + } + + public static final T castToJavaBean(Object obj, Class clazz) { + return cast(obj, clazz, ParserConfig.getGlobalInstance()); + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + public static final T cast(Object obj, Class clazz, ParserConfig mapping) { + if (obj == null) { + return null; + } + + if (clazz == null) { + throw new IllegalArgumentException("clazz is null"); + } + + if (clazz == obj.getClass()) { + return (T) obj; + } + + if (obj instanceof Map) { + if (clazz == Map.class) { + return (T) obj; + } + + return castToJavaBean((Map) obj, clazz, mapping); + } + + if (clazz.isArray()) { + if (obj instanceof Collection) { + + Collection collection = (Collection) obj; + int index = 0; + Object array = Array.newInstance(clazz.getComponentType(), collection.size()); + for (Object item : collection) { + Object value = cast(item, clazz.getComponentType(), mapping); + Array.set(array, index, value); + index++; + } + + return (T) array; + } + } + + if (clazz.isAssignableFrom(obj.getClass())) { + return (T) obj; + } + + if (clazz == boolean.class || clazz == Boolean.class) { + return (T) castToBoolean(obj); + } + + if (clazz == byte.class || clazz == Byte.class) { + return (T) castToByte(obj); + } + + // if (clazz == char.class || clazz == Character.class) { + // return (T) castToCharacter(obj); + // } + + if (clazz == short.class || clazz == Short.class) { + return (T) castToShort(obj); + } + + if (clazz == int.class || clazz == Integer.class) { + return (T) castToInt(obj); + } + + if (clazz == long.class || clazz == Long.class) { + return (T) castToLong(obj); + } + + if (clazz == float.class || clazz == Float.class) { + return (T) castToFloat(obj); + } + + if (clazz == double.class || clazz == Double.class) { + return (T) castToDouble(obj); + } + + if (clazz == String.class) { + return (T) castToString(obj); + } + + if (clazz == BigDecimal.class) { + return (T) castToBigDecimal(obj); + } + + if (clazz == BigInteger.class) { + return (T) castToBigInteger(obj); + } + + if (clazz == Date.class) { + return (T) castToDate(obj); + } + + if (clazz == java.sql.Date.class) { + return (T) castToSqlDate(obj); + } + + if (clazz == java.sql.Timestamp.class) { + return (T) castToTimestamp(obj); + } + + if (clazz.isEnum()) { + return (T) castToEnum(obj, clazz, mapping); + } + + if (Calendar.class.isAssignableFrom(clazz)) { + Date date = castToDate(obj); + Calendar calendar; + if (clazz == Calendar.class) { + calendar = Calendar.getInstance(); + } else { + try { + calendar = (Calendar) clazz.newInstance(); + } catch (Exception e) { + throw new JSONException("can not cast to : " + clazz.getName(), e); + } + } + calendar.setTime(date); + return (T) calendar; + } + + if (obj instanceof String) { + String strVal = (String) obj; + if (strVal.length() == 0) { + return null; + } + } + + throw new JSONException("can not cast to : " + clazz.getName()); + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + public static final T castToEnum(Object obj, Class clazz, ParserConfig mapping) { + try { + if (obj instanceof String) { + String name = (String) obj; + if (name.length() == 0) { + return null; + } + + return (T) Enum.valueOf((Class) clazz, name); + } + + if (obj instanceof Number) { + int ordinal = ((Number) obj).intValue(); + + Method method = clazz.getMethod("values"); + Object[] values = (Object[]) method.invoke(null); + for (Object value : values) { + Enum e = (Enum) value; + if (e.ordinal() == ordinal) { + return (T) e; + } + } + } + } catch (Exception ex) { + throw new JSONException("can not cast to : " + clazz.getName(), ex); + } + + throw new JSONException("can not cast to : " + clazz.getName()); + } + + @SuppressWarnings("unchecked") + public static final T cast(Object obj, Type type, ParserConfig mapping) { + if (obj == null) { + return null; + } + + if (type instanceof Class) { + return (T) cast(obj, (Class) type, mapping); + } + + if (type instanceof ParameterizedType) { + return (T) cast(obj, (ParameterizedType) type, mapping); + } + + if (obj instanceof String) { + String strVal = (String) obj; + if (strVal.length() == 0) { + return null; + } + } + + if (type instanceof TypeVariable) { + return (T) obj; + } + + throw new JSONException("can not cast to : " + type); + } + + @SuppressWarnings({ "rawtypes", "unchecked" }) + public static final T cast(Object obj, ParameterizedType type, ParserConfig mapping) { + Type rawTye = type.getRawType(); + + if (rawTye == List.class || rawTye == ArrayList.class) { + Type itemType = type.getActualTypeArguments()[0]; + + if (obj instanceof Iterable) { + List list = new ArrayList(); + + for (Iterator it = ((Iterable) obj).iterator(); it.hasNext();) { + Object item = it.next(); + list.add(cast(item, itemType, mapping)); + } + + return (T) list; + } + } + + if (rawTye == Map.class || rawTye == HashMap.class) { + Type keyType = type.getActualTypeArguments()[0]; + Type valueType = type.getActualTypeArguments()[1]; + + if (obj instanceof Map) { + Map map = new HashMap(); + + for (Map.Entry entry : ((Map) obj).entrySet()) { + Object key = cast(entry.getKey(), keyType, mapping); + Object value = cast(entry.getValue(), valueType, mapping); + + map.put(key, value); + } + + return (T) map; + } + } + + if (obj instanceof String) { + String strVal = (String) obj; + if (strVal.length() == 0) { + return null; + } + } + + if (type.getActualTypeArguments().length == 1) { + Type argType = type.getActualTypeArguments()[0]; + if (argType instanceof WildcardType) { + return (T) cast(obj, rawTye, mapping); + } + } + + throw new JSONException("can not cast to : " + type); + } + + @SuppressWarnings({ "unchecked" }) + public static final T castToJavaBean(Map map, Class clazz, ParserConfig mapping) { + try { + if (clazz == StackTraceElement.class) { + String declaringClass = (String) map.get("className"); + String methodName = (String) map.get("methodName"); + String fileName = (String) map.get("fileName"); + int lineNumber; + { + Number value = (Number) map.get("lineNumber"); + if (value == null) { + lineNumber = 0; + } else { + lineNumber = value.intValue(); + } + } + + return (T) new StackTraceElement(declaringClass, methodName, fileName, lineNumber); + } + + { + Object iClassObject = map.get(JSON.DEFAULT_TYPE_KEY); + if (iClassObject instanceof String) { + String className = (String) iClassObject; + + clazz = (Class) loadClass(className); + + if (clazz == null) { + throw new ClassNotFoundException(className + " not found"); + } + } + } + + if (clazz.isInterface()) { + JSONObject object; + + if (map instanceof JSONObject) { + object = (JSONObject) map; + } else { + object = new JSONObject(map); + } + + return (T) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), + new Class[] { clazz }, object); + } + + Map setters = mapping.getFieldDeserializers(clazz); + + T object = clazz.newInstance(); + + for (Map.Entry entry : setters.entrySet()) { + String key = entry.getKey(); + Method method = entry.getValue().getMethod(); + + if (map.containsKey(key)) { + Object value = map.get(key); + value = cast(value, method.getGenericParameterTypes()[0], mapping); + method.invoke(object, new Object[] { value }); + } + } + + return object; + } catch (Exception e) { + throw new JSONException(e.getMessage(), e); + } + } + + private static ConcurrentMap> mappings = new ConcurrentHashMap>(); + static { + addBaseClassMappings(); + } + + public static void addClassMapping(String className, Class clazz) { + if (className == null) { + className = clazz.getName(); + } + + mappings.put(className, clazz); + } + + public static void addBaseClassMappings() { + mappings.put("byte", byte.class); + mappings.put("short", short.class); + mappings.put("int", int.class); + mappings.put("long", long.class); + mappings.put("float", float.class); + mappings.put("double", double.class); + mappings.put("boolean", boolean.class); + mappings.put("char", char.class); + + mappings.put("[byte", byte[].class); + mappings.put("[short", short[].class); + mappings.put("[int", int[].class); + mappings.put("[long", long[].class); + mappings.put("[float", float[].class); + mappings.put("[double", double[].class); + mappings.put("[boolean", boolean[].class); + mappings.put("[char", char[].class); + + mappings.put(HashMap.class.getName(), HashMap.class); + } + + public static void clearClassMapping() { + mappings.clear(); + addBaseClassMappings(); + } + + public static Class loadClass(String className) { + if (className == null || className.length() == 0) { + return null; + } + + Class clazz = mappings.get(className); + + if (clazz != null) { + return clazz; + } + + if (className.charAt(0) == '[') { + Class componentType = loadClass(className.substring(1)); + return Array.newInstance(componentType, 0).getClass(); + } + + if (className.startsWith("L") && className.endsWith(";")) { + String newClassName = className.substring(1, className.length() - 1); + return loadClass(newClassName); + } + + try { + clazz = Thread.currentThread().getContextClassLoader().loadClass(className); + + addClassMapping(className, clazz); + + return clazz; + } catch (Throwable e) { + // skip + } + + try { + clazz = Class.forName(className); + + addClassMapping(className, clazz); + + return clazz; + } catch (Throwable e) { + // skip + } + + return clazz; + } + + public static List computeGetters(Class clazz, Map aliasMap) { + return computeGetters(clazz, aliasMap, true); + } + + public static List computeGetters(Class clazz, Map aliasMap, boolean sorted) { + Map fieldInfoMap = new LinkedHashMap(); + + for (Method method : clazz.getMethods()) { + String methodName = method.getName(); + + if (Modifier.isStatic(method.getModifiers())) { + continue; + } + + if (method.getReturnType().equals(Void.TYPE)) { + continue; + } + + if (method.getParameterTypes().length != 0) { + continue; + } + + if (method.getReturnType() == ClassLoader.class) { + continue; + } + + if (method.getName().equals("getMetaClass") + && method.getReturnType().getName().equals("groovy.lang.MetaClass")) { + continue; + } + + JSONField annotation = method.getAnnotation(JSONField.class); + + if (annotation == null) { + annotation = getSupperMethodAnnotation(clazz, method); + } + + if (annotation != null) { + if (!annotation.serialize()) { + continue; + } + + if (annotation.name().length() != 0) { + String propertyName = annotation.name(); + + if (aliasMap != null) { + propertyName = aliasMap.get(propertyName); + if (propertyName == null) { + continue; + } + } + + fieldInfoMap.put(propertyName, new FieldInfo(propertyName, method, null)); + continue; + } + } + + if (methodName.startsWith("get")) { + if (methodName.length() < 4) { + continue; + } + + if (methodName.equals("getClass")) { + continue; + } + + if (!Character.isUpperCase(methodName.charAt(3))) { + continue; + } + + String propertyName = Character.toLowerCase(methodName.charAt(3)) + methodName.substring(4); + + boolean ignore = isJSONTypeIgnore(clazz, propertyName); + + if (ignore) { + continue; + } + + Field field = ParserConfig.getField(clazz, propertyName); + if (field == null) { + field = ParserConfig.getField(clazz, methodName.substring(3)); + } + + if (field != null) { + JSONField fieldAnnotation = field.getAnnotation(JSONField.class); + + if (fieldAnnotation != null) { + if (!fieldAnnotation.serialize()) { + continue; + } + + if (fieldAnnotation.name().length() != 0) { + propertyName = fieldAnnotation.name(); + + if (aliasMap != null) { + propertyName = aliasMap.get(propertyName); + if (propertyName == null) { + continue; + } + } + } + } + } + + if (aliasMap != null) { + propertyName = aliasMap.get(propertyName); + if (propertyName == null) { + continue; + } + } + + fieldInfoMap.put(propertyName, new FieldInfo(propertyName, method, field)); + } + + if (methodName.startsWith("is")) { + if (methodName.length() < 3) { + continue; + } + + if (!Character.isUpperCase(methodName.charAt(2))) { + continue; + } + + String propertyName = Character.toLowerCase(methodName.charAt(2)) + methodName.substring(3); + + Field field = ParserConfig.getField(clazz, propertyName); + if (field != null) { + JSONField fieldAnnotation = field.getAnnotation(JSONField.class); + + if (fieldAnnotation != null) { + if (!fieldAnnotation.serialize()) { + continue; + } + + if (fieldAnnotation.name().length() != 0) { + propertyName = fieldAnnotation.name(); + + if (aliasMap != null) { + propertyName = aliasMap.get(propertyName); + if (propertyName == null) { + continue; + } + } + } + } + } + + if (aliasMap != null) { + propertyName = aliasMap.get(propertyName); + if (propertyName == null) { + continue; + } + } + + fieldInfoMap.put(propertyName, new FieldInfo(propertyName, method, field)); + } + } + + for (Field field : clazz.getFields()) { + if (Modifier.isStatic(field.getModifiers())) { + continue; + } + + if (!Modifier.isPublic(field.getModifiers())) { + continue; + } + + JSONField fieldAnnotation = field.getAnnotation(JSONField.class); + + String propertyName = field.getName(); + if (fieldAnnotation != null) { + if (!fieldAnnotation.serialize()) { + continue; + } + + if (fieldAnnotation.name().length() != 0) { + propertyName = fieldAnnotation.name(); + + if (aliasMap != null) { + propertyName = aliasMap.get(propertyName); + if (propertyName == null) { + continue; + } + } + } + } + + if (!fieldInfoMap.containsKey(field.getName())) { + fieldInfoMap.put(propertyName, new FieldInfo(propertyName, null, field)); + } + } + + List fieldInfoList = new ArrayList(); + + boolean containsAll = false; + String[] orders = null; + + JSONType annotation = clazz.getAnnotation(JSONType.class); + if (annotation != null) { + orders = annotation.orders(); + + if (orders != null && orders.length == fieldInfoMap.size()) { + containsAll = true; + for (String item : orders) { + if (!fieldInfoMap.containsKey(item)) { + containsAll = false; + break; + } + } + } else { + containsAll = false; + } + } + + if (containsAll) { + for (String item : orders) { + FieldInfo fieldInfo = fieldInfoMap.get(item); + fieldInfoList.add(fieldInfo); + } + } else { + for (FieldInfo fieldInfo : fieldInfoMap.values()) { + fieldInfoList.add(fieldInfo); + } + + if (sorted) { + Collections.sort(fieldInfoList); + } + } + + return fieldInfoList; + } + + public static JSONField getSupperMethodAnnotation(Class clazz, Method method) { + for (Class interfaceClass : clazz.getInterfaces()) { + for (Method interfaceMethod : interfaceClass.getMethods()) { + if (!interfaceMethod.getName().equals(method.getName())) { + continue; + } + + if (interfaceMethod.getParameterTypes().length != method.getParameterTypes().length) { + continue; + } + + boolean match = true; + for (int i = 0; i < interfaceMethod.getParameterTypes().length; ++i) { + if (!interfaceMethod.getParameterTypes()[i].equals(method.getParameterTypes()[i])) { + match = false; + break; + } + } + + if (!match) { + continue; + } + + JSONField annotation = interfaceMethod.getAnnotation(JSONField.class); + if (annotation != null) { + return annotation; + } + } + } + + return null; + } + + private static boolean isJSONTypeIgnore(Class clazz, String propertyName) { + JSONType jsonType = clazz.getAnnotation(JSONType.class); + + if (jsonType != null && jsonType.ignores() != null) { + for (String item : jsonType.ignores()) { + if (propertyName.equalsIgnoreCase(item)) { + return true; + } + } + } + + if (clazz.getSuperclass() != Object.class && clazz.getSuperclass() != null) { + if (isJSONTypeIgnore(clazz.getSuperclass(), propertyName)) { + return true; + } + } + + return false; + } + + public static Class getClass(Type type) { + if (type.getClass() == Class.class) { + return (Class) type; + } + + if (type instanceof ParameterizedType) { + return getClass(((ParameterizedType) type).getRawType()); + } + + return Object.class; + } } diff --git a/src/test/java/com/alibaba/json/bvt/bug/KeyBug_for_zhongl.java b/src/test/java/com/alibaba/json/bvt/bug/KeyBug_for_zhongl.java new file mode 100644 index 000000000..c5e29e239 --- /dev/null +++ b/src/test/java/com/alibaba/json/bvt/bug/KeyBug_for_zhongl.java @@ -0,0 +1,62 @@ +package com.alibaba.json.bvt.bug; + +import junit.framework.TestCase; + +import org.junit.Assert; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.annotation.JSONField; + +public class KeyBug_for_zhongl extends TestCase { + + public void testCustomedKey() throws Exception { + Assert.assertEquals("{\"uid\":1}", JSON.toJSONString(new V2(1))); + } + + public void testDeserialize() throws Exception { + Assert.assertEquals(123, JSON.parseObject("{\"uid\":123}", V2.class).id); + } + + public void testCustomedKey_static() throws Exception { + Assert.assertEquals("{\"uid\":1}", JSON.toJSONString(new VO(1))); + } + + public void testDeserialize_static() throws Exception { + Assert.assertEquals(123, JSON.parseObject("{\"uid\":123}", VO.class).id); + } + + public static class VO { + + @JSONField(name = "uid") + public int id; + + @JSONField(serialize = false) + public String name = "defaultName"; + + public VO(){ + + } + + VO(int id){ + this.id = id; + } + } + + private static class V2 { + + @JSONField(name = "uid") + public int id; + + @JSONField(serialize = false) + public String name = "defaultName"; + + private V2() { + + } + + private V2(int id) { + this.id = id; + } + } + +}