/src/main/java/com/alibaba/fastjson/util/DeserializeBeanInfo.java

https://github.com/flydream/fastjson · Java · 287 lines · 233 code · 54 blank · 0 comment · 66 complexity · 01d634cc5c590e0dc23ee21c970c2816 MD5 · raw file

  1. package com.alibaba.fastjson.util;
  2. import java.lang.annotation.Annotation;
  3. import java.lang.reflect.Constructor;
  4. import java.lang.reflect.Field;
  5. import java.lang.reflect.Method;
  6. import java.lang.reflect.Modifier;
  7. import java.lang.reflect.Type;
  8. import java.util.ArrayList;
  9. import java.util.List;
  10. import com.alibaba.fastjson.JSONException;
  11. import com.alibaba.fastjson.annotation.JSONCreator;
  12. import com.alibaba.fastjson.annotation.JSONField;
  13. public class DeserializeBeanInfo {
  14. private final Class<?> clazz;
  15. private final Type type;
  16. private Constructor<?> defaultConstructor;
  17. private Constructor<?> creatorConstructor;
  18. private Method factoryMethod;
  19. private final List<FieldInfo> fieldList = new ArrayList<FieldInfo>();
  20. public DeserializeBeanInfo(Class<?> clazz){
  21. super();
  22. this.clazz = clazz;
  23. this.type = clazz;
  24. }
  25. public Constructor<?> getDefaultConstructor() {
  26. return defaultConstructor;
  27. }
  28. public void setDefaultConstructor(Constructor<?> defaultConstructor) {
  29. this.defaultConstructor = defaultConstructor;
  30. }
  31. public Constructor<?> getCreatorConstructor() {
  32. return creatorConstructor;
  33. }
  34. public void setCreatorConstructor(Constructor<?> createConstructor) {
  35. this.creatorConstructor = createConstructor;
  36. }
  37. public Method getFactoryMethod() {
  38. return factoryMethod;
  39. }
  40. public void setFactoryMethod(Method factoryMethod) {
  41. this.factoryMethod = factoryMethod;
  42. }
  43. public Class<?> getClazz() {
  44. return clazz;
  45. }
  46. public Type getType() {
  47. return type;
  48. }
  49. public List<FieldInfo> getFieldList() {
  50. return fieldList;
  51. }
  52. public static DeserializeBeanInfo computeSetters(Class<?> clazz) {
  53. DeserializeBeanInfo beanInfo = new DeserializeBeanInfo(clazz);
  54. Constructor<?> defaultConstructor = getDefaultConstructor(clazz);
  55. if (defaultConstructor != null) {
  56. defaultConstructor.setAccessible(true);
  57. beanInfo.setDefaultConstructor(defaultConstructor);
  58. } else if (defaultConstructor == null && !(clazz.isInterface() || Modifier.isAbstract(clazz.getModifiers()))) {
  59. Constructor<?> creatorConstructor = getCreatorConstructor(clazz);
  60. if (creatorConstructor != null) {
  61. creatorConstructor.setAccessible(true);
  62. beanInfo.setCreatorConstructor(creatorConstructor);
  63. for (int i = 0; i < creatorConstructor.getParameterTypes().length; ++i) {
  64. Annotation[] paramAnnotations = creatorConstructor.getParameterAnnotations()[i];
  65. JSONField fieldAnnotation = null;
  66. for (Annotation paramAnnotation : paramAnnotations) {
  67. if (paramAnnotation instanceof JSONField) {
  68. fieldAnnotation = (JSONField) paramAnnotation;
  69. break;
  70. }
  71. }
  72. if (fieldAnnotation == null) {
  73. throw new JSONException("illegal json creator");
  74. }
  75. Class<?> fieldClass = creatorConstructor.getParameterTypes()[i];
  76. Type fieldType = creatorConstructor.getGenericParameterTypes()[i];
  77. Field field = getField(clazz, fieldAnnotation.name());
  78. if (field != null) {
  79. field.setAccessible(true);
  80. }
  81. FieldInfo fieldInfo = new FieldInfo(fieldAnnotation.name(), clazz, fieldClass, fieldType, null,
  82. field);
  83. beanInfo.getFieldList().add(fieldInfo);
  84. }
  85. return beanInfo;
  86. }
  87. Method factoryMethod = getFactoryMethod(clazz);
  88. if (factoryMethod != null) {
  89. factoryMethod.setAccessible(true);
  90. beanInfo.setFactoryMethod(factoryMethod);
  91. for (int i = 0; i < factoryMethod.getParameterTypes().length; ++i) {
  92. Annotation[] paramAnnotations = factoryMethod.getParameterAnnotations()[i];
  93. JSONField fieldAnnotation = null;
  94. for (Annotation paramAnnotation : paramAnnotations) {
  95. if (paramAnnotation instanceof JSONField) {
  96. fieldAnnotation = (JSONField) paramAnnotation;
  97. break;
  98. }
  99. }
  100. if (fieldAnnotation == null) {
  101. throw new JSONException("illegal json creator");
  102. }
  103. Class<?> fieldClass = factoryMethod.getParameterTypes()[i];
  104. Type fieldType = factoryMethod.getGenericParameterTypes()[i];
  105. Field field = getField(clazz, fieldAnnotation.name());
  106. if (field != null) {
  107. field.setAccessible(true);
  108. }
  109. FieldInfo fieldInfo = new FieldInfo(fieldAnnotation.name(), clazz, fieldClass, fieldType, null,
  110. field);
  111. beanInfo.getFieldList().add(fieldInfo);
  112. }
  113. return beanInfo;
  114. }
  115. throw new JSONException("default constructor not found. " + clazz);
  116. }
  117. for (Method method : clazz.getMethods()) {
  118. String methodName = method.getName();
  119. if (methodName.length() < 4) {
  120. continue;
  121. }
  122. if (Modifier.isStatic(method.getModifiers())) {
  123. continue;
  124. }
  125. if (!method.getReturnType().equals(Void.TYPE)) {
  126. continue;
  127. }
  128. if (method.getParameterTypes().length != 1) {
  129. continue;
  130. }
  131. JSONField annotation = method.getAnnotation(JSONField.class);
  132. if (annotation != null) {
  133. if (!annotation.deserialize()) {
  134. continue;
  135. }
  136. if (annotation.name().length() != 0) {
  137. String propertyName = annotation.name();
  138. beanInfo.getFieldList().add(new FieldInfo(propertyName, method, null));
  139. method.setAccessible(true);
  140. continue;
  141. }
  142. }
  143. if (methodName.startsWith("set") && Character.isUpperCase(methodName.charAt(3))) {
  144. String propertyName = Character.toLowerCase(methodName.charAt(3)) + methodName.substring(4);
  145. Field field = getField(clazz, propertyName);
  146. if (field != null) {
  147. JSONField fieldAnnotation = field.getAnnotation(JSONField.class);
  148. if (fieldAnnotation != null && fieldAnnotation.name().length() != 0) {
  149. propertyName = fieldAnnotation.name();
  150. beanInfo.getFieldList().add(new FieldInfo(propertyName, method, field));
  151. continue;
  152. }
  153. }
  154. beanInfo.getFieldList().add(new FieldInfo(propertyName, method, null));
  155. method.setAccessible(true);
  156. }
  157. }
  158. for (Field field : clazz.getFields()) {
  159. if (Modifier.isStatic(field.getModifiers())) {
  160. continue;
  161. }
  162. if (!Modifier.isPublic(field.getModifiers())) {
  163. continue;
  164. }
  165. boolean contains = false;
  166. for (FieldInfo item : beanInfo.getFieldList()) {
  167. if (item.getName().equals(field.getName())) {
  168. contains = true;
  169. continue;
  170. }
  171. }
  172. if (contains) {
  173. continue;
  174. }
  175. beanInfo.getFieldList().add(new FieldInfo(field.getName(), null, field));
  176. }
  177. return beanInfo;
  178. }
  179. public static Field getField(Class<?> clazz, String fieldName) {
  180. try {
  181. return clazz.getDeclaredField(fieldName);
  182. } catch (Exception e) {
  183. return null;
  184. }
  185. }
  186. public static Constructor<?> getDefaultConstructor(Class<?> clazz) {
  187. if (Modifier.isAbstract(clazz.getModifiers())) {
  188. return null;
  189. }
  190. Constructor<?> defaultConstructor = null;
  191. for (Constructor<?> constructor : clazz.getDeclaredConstructors()) {
  192. if (constructor.getParameterTypes().length == 0) {
  193. defaultConstructor = constructor;
  194. break;
  195. }
  196. }
  197. return defaultConstructor;
  198. }
  199. public static Constructor<?> getCreatorConstructor(Class<?> clazz) {
  200. Constructor<?> creatorConstructor = null;
  201. for (Constructor<?> constructor : clazz.getDeclaredConstructors()) {
  202. JSONCreator annotation = constructor.getAnnotation(JSONCreator.class);
  203. if (annotation != null) {
  204. if (creatorConstructor != null) {
  205. throw new JSONException("multi-json creator");
  206. }
  207. creatorConstructor = constructor;
  208. break;
  209. }
  210. }
  211. return creatorConstructor;
  212. }
  213. public static Method getFactoryMethod(Class<?> clazz) {
  214. Method factoryMethod = null;
  215. for (Method method : clazz.getDeclaredMethods()) {
  216. if (!Modifier.isStatic(method.getModifiers())) {
  217. continue;
  218. }
  219. if (!clazz.isAssignableFrom(method.getReturnType())) {
  220. continue;
  221. }
  222. JSONCreator annotation = method.getAnnotation(JSONCreator.class);
  223. if (annotation != null) {
  224. if (factoryMethod != null) {
  225. throw new JSONException("multi-json creator");
  226. }
  227. factoryMethod = method;
  228. break;
  229. }
  230. }
  231. return factoryMethod;
  232. }
  233. }