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

https://github.com/alibaba/fastjson · Java · 435 lines · 410 code · 25 blank · 0 comment · 53 complexity · 5f3519f5de0f351af5e29884efc4ef8e MD5 · raw file

  1. package com.alibaba.fastjson.parser.deserializer;
  2. import java.lang.reflect.ParameterizedType;
  3. import java.lang.reflect.Type;
  4. import java.util.*;
  5. import java.util.concurrent.ConcurrentHashMap;
  6. import java.util.concurrent.ConcurrentMap;
  7. import com.alibaba.fastjson.JSON;
  8. import com.alibaba.fastjson.JSONArray;
  9. import com.alibaba.fastjson.JSONException;
  10. import com.alibaba.fastjson.JSONObject;
  11. import com.alibaba.fastjson.parser.*;
  12. import com.alibaba.fastjson.parser.DefaultJSONParser.ResolveTask;
  13. public class MapDeserializer extends ContextObjectDeserializer implements ObjectDeserializer {
  14. public static MapDeserializer instance = new MapDeserializer();
  15. @SuppressWarnings("unchecked")
  16. public <T> T deserialze(DefaultJSONParser parser, Type type, Object fieldName, String format, int features)
  17. {
  18. if (type == JSONObject.class && parser.getFieldTypeResolver() == null) {
  19. return (T) parser.parseObject();
  20. }
  21. final JSONLexer lexer = parser.lexer;
  22. if (lexer.token() == JSONToken.NULL) {
  23. lexer.nextToken(JSONToken.COMMA);
  24. return null;
  25. }
  26. boolean unmodifiableMap = type instanceof Class
  27. && "java.util.Collections$UnmodifiableMap".equals(((Class) type).getName());
  28. Map<Object, Object> map = (lexer.getFeatures() & Feature.OrderedField.mask) != 0
  29. ? createMap(type, lexer.getFeatures())
  30. : createMap(type);
  31. ParseContext context = parser.getContext();
  32. try {
  33. parser.setContext(context, map, fieldName);
  34. T t = (T) deserialze(parser, type, fieldName, map, features);
  35. if (unmodifiableMap) {
  36. t = (T) Collections.unmodifiableMap((Map) t);
  37. }
  38. return t;
  39. } finally {
  40. parser.setContext(context);
  41. }
  42. }
  43. protected Object deserialze(DefaultJSONParser parser, Type type, Object fieldName, Map map) {
  44. return deserialze(parser, type, fieldName, map, 0);
  45. }
  46. @SuppressWarnings({ "rawtypes", "unchecked" })
  47. protected Object deserialze(DefaultJSONParser parser, Type type, Object fieldName, Map map, int features) {
  48. if (type instanceof ParameterizedType) {
  49. ParameterizedType parameterizedType = (ParameterizedType) type;
  50. Type keyType = parameterizedType.getActualTypeArguments()[0];
  51. Type valueType = null;
  52. if(map.getClass().getName().equals("org.springframework.util.LinkedMultiValueMap")){
  53. valueType = List.class;
  54. }else{
  55. valueType = parameterizedType.getActualTypeArguments()[1];
  56. }
  57. if (String.class == keyType) {
  58. return parseMap(parser, (Map<String, Object>) map, valueType, fieldName, features);
  59. } else {
  60. return parseMap(parser, map, keyType, valueType, fieldName);
  61. }
  62. } else {
  63. return parser.parseObject(map, fieldName);
  64. }
  65. }
  66. public static Map parseMap(DefaultJSONParser parser, Map<String, Object> map, Type valueType, Object fieldName) {
  67. return parseMap(parser, map, valueType, fieldName, 0);
  68. }
  69. @SuppressWarnings("rawtypes")
  70. public static Map parseMap(DefaultJSONParser parser, Map<String, Object> map, Type valueType, Object fieldName, int features) {
  71. JSONLexer lexer = parser.lexer;
  72. int token = lexer.token();
  73. if (token != JSONToken.LBRACE) {
  74. if (token == JSONToken.LITERAL_STRING) {
  75. String stringVal = lexer.stringVal();
  76. if (stringVal.length() == 0 || stringVal.equals("null")) {
  77. return null;
  78. }
  79. }
  80. String msg = "syntax error, expect {, actual " + lexer.tokenName();
  81. if (fieldName instanceof String) {
  82. msg += ", fieldName ";
  83. msg += fieldName;
  84. }
  85. msg += ", ";
  86. msg += lexer.info();
  87. if (token != JSONToken.LITERAL_STRING) {
  88. JSONArray array = new JSONArray();
  89. parser.parseArray(array, fieldName);
  90. if (array.size() == 1) {
  91. Object first = array.get(0);
  92. if (first instanceof JSONObject) {
  93. return (JSONObject) first;
  94. }
  95. }
  96. }
  97. throw new JSONException(msg);
  98. }
  99. ParseContext context = parser.getContext();
  100. try {
  101. for (int i = 0;;++i) {
  102. lexer.skipWhitespace();
  103. char ch = lexer.getCurrent();
  104. if (lexer.isEnabled(Feature.AllowArbitraryCommas)) {
  105. while (ch == ',') {
  106. lexer.next();
  107. lexer.skipWhitespace();
  108. ch = lexer.getCurrent();
  109. }
  110. }
  111. String key;
  112. if (ch == '"') {
  113. key = lexer.scanSymbol(parser.getSymbolTable(), '"');
  114. lexer.skipWhitespace();
  115. ch = lexer.getCurrent();
  116. if (ch != ':') {
  117. throw new JSONException("expect ':' at " + lexer.pos());
  118. }
  119. } else if (ch == '}') {
  120. lexer.next();
  121. lexer.resetStringPosition();
  122. lexer.nextToken(JSONToken.COMMA);
  123. return map;
  124. } else if (ch == '\'') {
  125. if (!lexer.isEnabled(Feature.AllowSingleQuotes)) {
  126. throw new JSONException("syntax error");
  127. }
  128. key = lexer.scanSymbol(parser.getSymbolTable(), '\'');
  129. lexer.skipWhitespace();
  130. ch = lexer.getCurrent();
  131. if (ch != ':') {
  132. throw new JSONException("expect ':' at " + lexer.pos());
  133. }
  134. } else {
  135. if (!lexer.isEnabled(Feature.AllowUnQuotedFieldNames)) {
  136. throw new JSONException("syntax error");
  137. }
  138. key = lexer.scanSymbolUnQuoted(parser.getSymbolTable());
  139. lexer.skipWhitespace();
  140. ch = lexer.getCurrent();
  141. if (ch != ':') {
  142. throw new JSONException("expect ':' at " + lexer.pos() + ", actual " + ch);
  143. }
  144. }
  145. lexer.next();
  146. lexer.skipWhitespace();
  147. ch = lexer.getCurrent();
  148. lexer.resetStringPosition();
  149. if (key == JSON.DEFAULT_TYPE_KEY
  150. && !lexer.isEnabled(Feature.DisableSpecialKeyDetect)
  151. && !Feature.isEnabled(features, Feature.DisableSpecialKeyDetect)
  152. ) {
  153. String typeName = lexer.scanSymbol(parser.getSymbolTable(), '"');
  154. final ParserConfig config = parser.getConfig();
  155. Class<?> clazz;
  156. if (typeName.equals("java.util.HashMap")) {
  157. clazz = java.util.HashMap.class;
  158. } else if (typeName.equals("java.util.LinkedHashMap")) {
  159. clazz = java.util.LinkedHashMap.class;
  160. } else if (config.isSafeMode()) {
  161. clazz = java.util.HashMap.class;
  162. } else {
  163. try {
  164. clazz = config.checkAutoType(typeName, null, lexer.getFeatures());
  165. } catch (JSONException ex) {
  166. // skip
  167. clazz = java.util.HashMap.class;
  168. }
  169. }
  170. if (Map.class.isAssignableFrom(clazz) ) {
  171. lexer.nextToken(JSONToken.COMMA);
  172. if (lexer.token() == JSONToken.RBRACE) {
  173. lexer.nextToken(JSONToken.COMMA);
  174. return map;
  175. }
  176. continue;
  177. }
  178. ObjectDeserializer deserializer = config.getDeserializer(clazz);
  179. lexer.nextToken(JSONToken.COMMA);
  180. parser.setResolveStatus(DefaultJSONParser.TypeNameRedirect);
  181. if (context != null && !(fieldName instanceof Integer)) {
  182. parser.popContext();
  183. }
  184. return (Map) deserializer.deserialze(parser, clazz, fieldName);
  185. }
  186. Object value;
  187. lexer.nextToken();
  188. if (i != 0) {
  189. parser.setContext(context);
  190. }
  191. if (lexer.token() == JSONToken.NULL) {
  192. value = null;
  193. lexer.nextToken();
  194. } else {
  195. value = parser.parseObject(valueType, key);
  196. }
  197. map.put(key, value);
  198. parser.checkMapResolve(map, key);
  199. parser.setContext(context, value, key);
  200. parser.setContext(context);
  201. final int tok = lexer.token();
  202. if (tok == JSONToken.EOF || tok == JSONToken.RBRACKET) {
  203. return map;
  204. }
  205. if (tok == JSONToken.RBRACE) {
  206. lexer.nextToken();
  207. return map;
  208. }
  209. }
  210. } finally {
  211. parser.setContext(context);
  212. }
  213. }
  214. public static Object parseMap(DefaultJSONParser parser, Map<Object, Object> map, Type keyType, Type valueType,
  215. Object fieldName) {
  216. JSONLexer lexer = parser.lexer;
  217. if (lexer.token() != JSONToken.LBRACE && lexer.token() != JSONToken.COMMA) {
  218. throw new JSONException("syntax error, expect {, actual " + lexer.tokenName());
  219. }
  220. ObjectDeserializer keyDeserializer = parser.getConfig().getDeserializer(keyType);
  221. ObjectDeserializer valueDeserializer = parser.getConfig().getDeserializer(valueType);
  222. lexer.nextToken(keyDeserializer.getFastMatchToken());
  223. ParseContext context = parser.getContext();
  224. try {
  225. for (;;) {
  226. if (lexer.token() == JSONToken.RBRACE) {
  227. lexer.nextToken(JSONToken.COMMA);
  228. break;
  229. }
  230. if (lexer.token() == JSONToken.LITERAL_STRING //
  231. && lexer.isRef() //
  232. && !lexer.isEnabled(Feature.DisableSpecialKeyDetect) //
  233. ) {
  234. Object object = null;
  235. lexer.nextTokenWithColon(JSONToken.LITERAL_STRING);
  236. if (lexer.token() == JSONToken.LITERAL_STRING) {
  237. String ref = lexer.stringVal();
  238. if ("..".equals(ref)) {
  239. ParseContext parentContext = context.parent;
  240. object = parentContext.object;
  241. } else if ("$".equals(ref)) {
  242. ParseContext rootContext = context;
  243. while (rootContext.parent != null) {
  244. rootContext = rootContext.parent;
  245. }
  246. object = rootContext.object;
  247. } else {
  248. parser.addResolveTask(new ResolveTask(context, ref));
  249. parser.setResolveStatus(DefaultJSONParser.NeedToResolve);
  250. }
  251. } else {
  252. throw new JSONException("illegal ref, " + JSONToken.name(lexer.token()));
  253. }
  254. lexer.nextToken(JSONToken.RBRACE);
  255. if (lexer.token() != JSONToken.RBRACE) {
  256. throw new JSONException("illegal ref");
  257. }
  258. lexer.nextToken(JSONToken.COMMA);
  259. // parser.setContext(context, map, fieldName);
  260. // parser.setContext(context);
  261. return object;
  262. }
  263. if (map.size() == 0 //
  264. && lexer.token() == JSONToken.LITERAL_STRING //
  265. && JSON.DEFAULT_TYPE_KEY.equals(lexer.stringVal()) //
  266. && !lexer.isEnabled(Feature.DisableSpecialKeyDetect)) {
  267. lexer.nextTokenWithColon(JSONToken.LITERAL_STRING);
  268. lexer.nextToken(JSONToken.COMMA);
  269. if (lexer.token() == JSONToken.RBRACE) {
  270. lexer.nextToken();
  271. return map;
  272. }
  273. lexer.nextToken(keyDeserializer.getFastMatchToken());
  274. }
  275. Object key;
  276. if (lexer.token() == JSONToken.LITERAL_STRING
  277. && keyDeserializer instanceof JavaBeanDeserializer
  278. ) {
  279. String keyStrValue = lexer.stringVal();
  280. lexer.nextToken();
  281. DefaultJSONParser keyParser = new DefaultJSONParser(keyStrValue, parser.getConfig(), parser.getLexer().getFeatures());
  282. keyParser.setDateFormat(parser.getDateFomartPattern());
  283. key = keyDeserializer.deserialze(keyParser, keyType, null);
  284. } else {
  285. key = keyDeserializer.deserialze(parser, keyType, null);
  286. }
  287. if (lexer.token() != JSONToken.COLON) {
  288. throw new JSONException("syntax error, expect :, actual " + lexer.token());
  289. }
  290. lexer.nextToken(valueDeserializer.getFastMatchToken());
  291. Object value = valueDeserializer.deserialze(parser, valueType, key);
  292. parser.checkMapResolve(map, key);
  293. map.put(key, value);
  294. if (lexer.token() == JSONToken.COMMA) {
  295. lexer.nextToken(keyDeserializer.getFastMatchToken());
  296. }
  297. }
  298. } finally {
  299. parser.setContext(context);
  300. }
  301. return map;
  302. }
  303. public Map<Object, Object> createMap(Type type) {
  304. return createMap(type, JSON.DEFAULT_GENERATE_FEATURE);
  305. }
  306. @SuppressWarnings({ "unchecked", "rawtypes" })
  307. public Map<Object, Object> createMap(Type type, int featrues) {
  308. if (type == Properties.class) {
  309. return new Properties();
  310. }
  311. if (type == Hashtable.class) {
  312. return new Hashtable();
  313. }
  314. if (type == IdentityHashMap.class) {
  315. return new IdentityHashMap();
  316. }
  317. if (type == SortedMap.class || type == TreeMap.class) {
  318. return new TreeMap();
  319. }
  320. if (type == ConcurrentMap.class || type == ConcurrentHashMap.class) {
  321. return new ConcurrentHashMap();
  322. }
  323. if (type == Map.class) {
  324. return (featrues & Feature.OrderedField.mask) != 0
  325. ? new LinkedHashMap()
  326. : new HashMap();
  327. }
  328. if (type == HashMap.class) {
  329. return new HashMap();
  330. }
  331. if (type == LinkedHashMap.class) {
  332. return new LinkedHashMap();
  333. }
  334. if (type instanceof ParameterizedType) {
  335. ParameterizedType parameterizedType = (ParameterizedType) type;
  336. Type rawType = parameterizedType.getRawType();
  337. if (EnumMap.class.equals(rawType)) {
  338. Type[] actualArgs = parameterizedType.getActualTypeArguments();
  339. return new EnumMap((Class) actualArgs[0]);
  340. }
  341. return createMap(rawType, featrues);
  342. }
  343. Class<?> clazz = (Class<?>) type;
  344. if (clazz.isInterface()) {
  345. throw new JSONException("unsupport type " + type);
  346. }
  347. if ("java.util.Collections$UnmodifiableMap".equals(clazz.getName())) {
  348. return new HashMap();
  349. }
  350. try {
  351. return (Map<Object, Object>) clazz.newInstance();
  352. } catch (Exception e) {
  353. throw new JSONException("unsupport type " + type, e);
  354. }
  355. }
  356. public int getFastMatchToken() {
  357. return JSONToken.LBRACE;
  358. }
  359. }