PageRenderTime 34ms CodeModel.GetById 0ms RepoModel.GetById 2ms app.codeStats 0ms

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

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