/src/main/java/com/alibaba/fastjson/parser/deserializer/FieldDeserializer.java

https://github.com/alibaba/fastjson · Java · 261 lines · 223 code · 31 blank · 7 comment · 109 complexity · d61f9a54b836018692f8da80d0ef8f9d MD5 · raw file

  1. package com.alibaba.fastjson.parser.deserializer;
  2. import com.alibaba.fastjson.JSONException;
  3. import com.alibaba.fastjson.parser.DefaultJSONParser;
  4. import com.alibaba.fastjson.parser.ParserConfig;
  5. import com.alibaba.fastjson.serializer.BeanContext;
  6. import com.alibaba.fastjson.util.FieldInfo;
  7. import com.alibaba.fastjson.util.TypeUtils;
  8. import java.lang.reflect.*;
  9. import java.util.Collection;
  10. import java.util.Collections;
  11. import java.util.Map;
  12. import java.util.concurrent.atomic.AtomicBoolean;
  13. import java.util.concurrent.atomic.AtomicInteger;
  14. import java.util.concurrent.atomic.AtomicLong;
  15. public abstract class FieldDeserializer {
  16. public final FieldInfo fieldInfo;
  17. protected final Class<?> clazz;
  18. protected BeanContext beanContext;
  19. public FieldDeserializer(Class<?> clazz, FieldInfo fieldInfo) {
  20. this.clazz = clazz;
  21. this.fieldInfo = fieldInfo;
  22. }
  23. public Class<?> getOwnerClass() {
  24. return clazz;
  25. }
  26. public abstract void parseField(DefaultJSONParser parser, Object object, Type objectType,
  27. Map<String, Object> fieldValues);
  28. public int getFastMatchToken() {
  29. return 0;
  30. }
  31. public void setValue(Object object, boolean value) {
  32. setValue(object, Boolean.valueOf(value));
  33. }
  34. public void setValue(Object object, int value) {
  35. setValue(object, Integer.valueOf(value));
  36. }
  37. public void setValue(Object object, long value) {
  38. setValue(object, Long.valueOf(value));
  39. }
  40. public void setValue(Object object, String value) {
  41. setValue(object, (Object) value);
  42. }
  43. @SuppressWarnings({"rawtypes", "unchecked"})
  44. public void setValue(Object object, Object value) {
  45. if (value == null //
  46. && fieldInfo.fieldClass.isPrimitive()) {
  47. return;
  48. } else if (fieldInfo.fieldClass == String.class
  49. && fieldInfo.format != null
  50. && fieldInfo.format.equals("trim")) {
  51. value = ((String) value).trim();
  52. }
  53. try {
  54. Method method = fieldInfo.method;
  55. if (method != null) {
  56. if (fieldInfo.getOnly) {
  57. if (fieldInfo.fieldClass == AtomicInteger.class) {
  58. AtomicInteger atomic = (AtomicInteger) method.invoke(object);
  59. if (atomic != null) {
  60. atomic.set(((AtomicInteger) value).get());
  61. } else {
  62. degradeValueAssignment(fieldInfo.field, method, object, value);
  63. }
  64. } else if (fieldInfo.fieldClass == AtomicLong.class) {
  65. AtomicLong atomic = (AtomicLong) method.invoke(object);
  66. if (atomic != null) {
  67. atomic.set(((AtomicLong) value).get());
  68. } else {
  69. degradeValueAssignment(fieldInfo.field, method, object, value);
  70. }
  71. } else if (fieldInfo.fieldClass == AtomicBoolean.class) {
  72. AtomicBoolean atomic = (AtomicBoolean) method.invoke(object);
  73. if (atomic != null) {
  74. atomic.set(((AtomicBoolean) value).get());
  75. } else {
  76. degradeValueAssignment(fieldInfo.field, method, object, value);
  77. }
  78. } else if (Map.class.isAssignableFrom(method.getReturnType())) {
  79. Map map = null;
  80. try {
  81. map = (Map) method.invoke(object);
  82. } catch (InvocationTargetException e) {
  83. degradeValueAssignment(fieldInfo.field, method, object, value);
  84. return;
  85. }
  86. if (map != null) {
  87. if (map == Collections.emptyMap()) {
  88. return;
  89. }
  90. if (map.isEmpty() && ((Map) value).isEmpty()) {
  91. return;
  92. }
  93. String mapClassName = map.getClass().getName();
  94. if (mapClassName.equals("java.util.ImmutableCollections$Map1")
  95. || mapClassName.equals("java.util.ImmutableCollections$MapN")
  96. || mapClassName.startsWith("java.util.Collections$Unmodifiable")) {
  97. // skip
  98. return;
  99. }
  100. if (map.getClass().getName().equals("kotlin.collections.EmptyMap")) {
  101. degradeValueAssignment(fieldInfo.field, method, object, value);
  102. return;
  103. }
  104. map.putAll((Map) value);
  105. } else if (value != null) {
  106. degradeValueAssignment(fieldInfo.field, method, object, value);
  107. }
  108. } else {
  109. Collection collection = null;
  110. try {
  111. collection = (Collection) method.invoke(object);
  112. } catch (InvocationTargetException e) {
  113. degradeValueAssignment(fieldInfo.field, method, object, value);
  114. return;
  115. }
  116. if (collection != null && value != null) {
  117. String collectionClassName = collection.getClass().getName();
  118. if (collection == Collections.emptySet()
  119. || collection == Collections.emptyList()
  120. || collectionClassName == "java.util.ImmutableCollections$ListN"
  121. || collectionClassName == "java.util.ImmutableCollections$List12"
  122. || collectionClassName.startsWith("java.util.Collections$Unmodifiable")) {
  123. // skip
  124. return;
  125. }
  126. if (!collection.isEmpty()) {
  127. collection.clear();
  128. } else if (((Collection) value).isEmpty()) {
  129. return; //skip
  130. }
  131. if (collectionClassName.equals("kotlin.collections.EmptyList")
  132. || collectionClassName.equals("kotlin.collections.EmptySet")) {
  133. degradeValueAssignment(fieldInfo.field, method, object, value);
  134. return;
  135. }
  136. collection.addAll((Collection) value);
  137. } else if (collection == null && value != null) {
  138. degradeValueAssignment(fieldInfo.field, method, object, value);
  139. }
  140. }
  141. } else {
  142. method.invoke(object, value);
  143. }
  144. } else {
  145. final Field field = fieldInfo.field;
  146. if (fieldInfo.getOnly) {
  147. if (fieldInfo.fieldClass == AtomicInteger.class) {
  148. AtomicInteger atomic = (AtomicInteger) field.get(object);
  149. if (atomic != null) {
  150. atomic.set(((AtomicInteger) value).get());
  151. }
  152. } else if (fieldInfo.fieldClass == AtomicLong.class) {
  153. AtomicLong atomic = (AtomicLong) field.get(object);
  154. if (atomic != null) {
  155. atomic.set(((AtomicLong) value).get());
  156. }
  157. } else if (fieldInfo.fieldClass == AtomicBoolean.class) {
  158. AtomicBoolean atomic = (AtomicBoolean) field.get(object);
  159. if (atomic != null) {
  160. atomic.set(((AtomicBoolean) value).get());
  161. }
  162. } else if (Map.class.isAssignableFrom(fieldInfo.fieldClass)) {
  163. Map map = (Map) field.get(object);
  164. if (map != null) {
  165. if (map == Collections.emptyMap()
  166. || map.getClass().getName().startsWith("java.util.Collections$Unmodifiable")) {
  167. // skip
  168. return;
  169. }
  170. map.putAll((Map) value);
  171. }
  172. } else {
  173. Collection collection = (Collection) field.get(object);
  174. if (collection != null && value != null) {
  175. if (collection == Collections.emptySet()
  176. || collection == Collections.emptyList()
  177. || collection.getClass().getName().startsWith("java.util.Collections$Unmodifiable")) {
  178. // skip
  179. return;
  180. }
  181. collection.clear();
  182. collection.addAll((Collection) value);
  183. }
  184. }
  185. } else {
  186. if (field != null) {
  187. field.set(object, value);
  188. }
  189. }
  190. }
  191. } catch (Exception e) {
  192. throw new JSONException("set property error, " + clazz.getName() + "#" + fieldInfo.name, e);
  193. }
  194. }
  195. /**
  196. * kotlin代理类property的get方法会抛未初始化异常,用set方法直接赋值
  197. */
  198. private static boolean degradeValueAssignment(
  199. Field field,
  200. Method getMethod,
  201. Object object,
  202. Object value
  203. ) throws InvocationTargetException, IllegalAccessException {
  204. if (setFieldValue(field, object, value)) {
  205. return true;
  206. }
  207. try {
  208. Method setMethod = object
  209. .getClass()
  210. .getDeclaredMethod("set" + getMethod.getName().substring(3), getMethod.getReturnType());
  211. setMethod.invoke(object, value);
  212. return true;
  213. } catch (InvocationTargetException ignored) {
  214. } catch (NoSuchMethodException ignored) {
  215. } catch (IllegalAccessException ignored) {
  216. }
  217. return false;
  218. }
  219. private static boolean setFieldValue(Field field, Object object, Object value) throws IllegalAccessException {
  220. if (field != null
  221. && !Modifier.isFinal(field.getModifiers())) {
  222. field.set(object, value);
  223. return true;
  224. }
  225. return false;
  226. }
  227. public void setWrappedValue(String key, Object value) {
  228. throw new JSONException("TODO");
  229. }
  230. }