/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
- package com.alibaba.fastjson.parser.deserializer;
- import java.lang.reflect.ParameterizedType;
- import java.lang.reflect.Type;
- import java.util.*;
- import java.util.concurrent.ConcurrentHashMap;
- import java.util.concurrent.ConcurrentMap;
- import com.alibaba.fastjson.JSON;
- import com.alibaba.fastjson.JSONArray;
- import com.alibaba.fastjson.JSONException;
- import com.alibaba.fastjson.JSONObject;
- import com.alibaba.fastjson.parser.*;
- import com.alibaba.fastjson.parser.DefaultJSONParser.ResolveTask;
- public class MapDeserializer extends ContextObjectDeserializer implements ObjectDeserializer {
- public static MapDeserializer instance = new MapDeserializer();
- @SuppressWarnings("unchecked")
- public <T> T deserialze(DefaultJSONParser parser, Type type, Object fieldName, String format, int features)
- {
- if (type == JSONObject.class && parser.getFieldTypeResolver() == null) {
- return (T) parser.parseObject();
- }
-
- final JSONLexer lexer = parser.lexer;
- if (lexer.token() == JSONToken.NULL) {
- lexer.nextToken(JSONToken.COMMA);
- return null;
- }
- boolean unmodifiableMap = type instanceof Class
- && "java.util.Collections$UnmodifiableMap".equals(((Class) type).getName());
- Map<Object, Object> map = (lexer.getFeatures() & Feature.OrderedField.mask) != 0
- ? createMap(type, lexer.getFeatures())
- : createMap(type);
- ParseContext context = parser.getContext();
- try {
- parser.setContext(context, map, fieldName);
- T t = (T) deserialze(parser, type, fieldName, map, features);
- if (unmodifiableMap) {
- t = (T) Collections.unmodifiableMap((Map) t);
- }
- return t;
- } finally {
- parser.setContext(context);
- }
- }
- protected Object deserialze(DefaultJSONParser parser, Type type, Object fieldName, Map map) {
- return deserialze(parser, type, fieldName, map, 0);
- }
- @SuppressWarnings({ "rawtypes", "unchecked" })
- protected Object deserialze(DefaultJSONParser parser, Type type, Object fieldName, Map map, int features) {
- if (type instanceof ParameterizedType) {
- ParameterizedType parameterizedType = (ParameterizedType) type;
- Type keyType = parameterizedType.getActualTypeArguments()[0];
- Type valueType = null;
- if(map.getClass().getName().equals("org.springframework.util.LinkedMultiValueMap")){
- valueType = List.class;
- }else{
- valueType = parameterizedType.getActualTypeArguments()[1];
- }
- if (String.class == keyType) {
- return parseMap(parser, (Map<String, Object>) map, valueType, fieldName, features);
- } else {
- return parseMap(parser, map, keyType, valueType, fieldName);
- }
- } else {
- return parser.parseObject(map, fieldName);
- }
- }
- public static Map parseMap(DefaultJSONParser parser, Map<String, Object> map, Type valueType, Object fieldName) {
- return parseMap(parser, map, valueType, fieldName, 0);
- }
-
- @SuppressWarnings("rawtypes")
- public static Map parseMap(DefaultJSONParser parser, Map<String, Object> map, Type valueType, Object fieldName, int features) {
- JSONLexer lexer = parser.lexer;
- int token = lexer.token();
- if (token != JSONToken.LBRACE) {
- if (token == JSONToken.LITERAL_STRING) {
- String stringVal = lexer.stringVal();
- if (stringVal.length() == 0 || stringVal.equals("null")) {
- return null;
- }
- }
- String msg = "syntax error, expect {, actual " + lexer.tokenName();
- if (fieldName instanceof String) {
- msg += ", fieldName ";
- msg += fieldName;
- }
- msg += ", ";
- msg += lexer.info();
- if (token != JSONToken.LITERAL_STRING) {
- JSONArray array = new JSONArray();
- parser.parseArray(array, fieldName);
- if (array.size() == 1) {
- Object first = array.get(0);
- if (first instanceof JSONObject) {
- return (JSONObject) first;
- }
- }
- }
- throw new JSONException(msg);
- }
- ParseContext context = parser.getContext();
- try {
- for (int i = 0;;++i) {
- lexer.skipWhitespace();
- char ch = lexer.getCurrent();
- if (lexer.isEnabled(Feature.AllowArbitraryCommas)) {
- while (ch == ',') {
- lexer.next();
- lexer.skipWhitespace();
- ch = lexer.getCurrent();
- }
- }
- String key;
- if (ch == '"') {
- key = lexer.scanSymbol(parser.getSymbolTable(), '"');
- lexer.skipWhitespace();
- ch = lexer.getCurrent();
- if (ch != ':') {
- throw new JSONException("expect ':' at " + lexer.pos());
- }
- } else if (ch == '}') {
- lexer.next();
- lexer.resetStringPosition();
- lexer.nextToken(JSONToken.COMMA);
- return map;
- } else if (ch == '\'') {
- if (!lexer.isEnabled(Feature.AllowSingleQuotes)) {
- throw new JSONException("syntax error");
- }
- key = lexer.scanSymbol(parser.getSymbolTable(), '\'');
- lexer.skipWhitespace();
- ch = lexer.getCurrent();
- if (ch != ':') {
- throw new JSONException("expect ':' at " + lexer.pos());
- }
- } else {
- if (!lexer.isEnabled(Feature.AllowUnQuotedFieldNames)) {
- throw new JSONException("syntax error");
- }
- key = lexer.scanSymbolUnQuoted(parser.getSymbolTable());
- lexer.skipWhitespace();
- ch = lexer.getCurrent();
- if (ch != ':') {
- throw new JSONException("expect ':' at " + lexer.pos() + ", actual " + ch);
- }
- }
- lexer.next();
- lexer.skipWhitespace();
- ch = lexer.getCurrent();
- lexer.resetStringPosition();
- if (key == JSON.DEFAULT_TYPE_KEY
- && !lexer.isEnabled(Feature.DisableSpecialKeyDetect)
- && !Feature.isEnabled(features, Feature.DisableSpecialKeyDetect)
- ) {
- String typeName = lexer.scanSymbol(parser.getSymbolTable(), '"');
- final ParserConfig config = parser.getConfig();
- Class<?> clazz;
- if (typeName.equals("java.util.HashMap")) {
- clazz = java.util.HashMap.class;
- } else if (typeName.equals("java.util.LinkedHashMap")) {
- clazz = java.util.LinkedHashMap.class;
- } else if (config.isSafeMode()) {
- clazz = java.util.HashMap.class;
- } else {
- try {
- clazz = config.checkAutoType(typeName, null, lexer.getFeatures());
- } catch (JSONException ex) {
- // skip
- clazz = java.util.HashMap.class;
- }
- }
- if (Map.class.isAssignableFrom(clazz) ) {
- lexer.nextToken(JSONToken.COMMA);
- if (lexer.token() == JSONToken.RBRACE) {
- lexer.nextToken(JSONToken.COMMA);
- return map;
- }
- continue;
- }
- ObjectDeserializer deserializer = config.getDeserializer(clazz);
- lexer.nextToken(JSONToken.COMMA);
- parser.setResolveStatus(DefaultJSONParser.TypeNameRedirect);
- if (context != null && !(fieldName instanceof Integer)) {
- parser.popContext();
- }
- return (Map) deserializer.deserialze(parser, clazz, fieldName);
- }
- Object value;
- lexer.nextToken();
- if (i != 0) {
- parser.setContext(context);
- }
-
- if (lexer.token() == JSONToken.NULL) {
- value = null;
- lexer.nextToken();
- } else {
- value = parser.parseObject(valueType, key);
- }
- map.put(key, value);
- parser.checkMapResolve(map, key);
- parser.setContext(context, value, key);
- parser.setContext(context);
- final int tok = lexer.token();
- if (tok == JSONToken.EOF || tok == JSONToken.RBRACKET) {
- return map;
- }
- if (tok == JSONToken.RBRACE) {
- lexer.nextToken();
- return map;
- }
- }
- } finally {
- parser.setContext(context);
- }
- }
-
- public static Object parseMap(DefaultJSONParser parser, Map<Object, Object> map, Type keyType, Type valueType,
- Object fieldName) {
- JSONLexer lexer = parser.lexer;
- if (lexer.token() != JSONToken.LBRACE && lexer.token() != JSONToken.COMMA) {
- throw new JSONException("syntax error, expect {, actual " + lexer.tokenName());
- }
- ObjectDeserializer keyDeserializer = parser.getConfig().getDeserializer(keyType);
- ObjectDeserializer valueDeserializer = parser.getConfig().getDeserializer(valueType);
- lexer.nextToken(keyDeserializer.getFastMatchToken());
- ParseContext context = parser.getContext();
- try {
- for (;;) {
- if (lexer.token() == JSONToken.RBRACE) {
- lexer.nextToken(JSONToken.COMMA);
- break;
- }
- if (lexer.token() == JSONToken.LITERAL_STRING //
- && lexer.isRef() //
- && !lexer.isEnabled(Feature.DisableSpecialKeyDetect) //
- ) {
- Object object = null;
- lexer.nextTokenWithColon(JSONToken.LITERAL_STRING);
- if (lexer.token() == JSONToken.LITERAL_STRING) {
- String ref = lexer.stringVal();
- if ("..".equals(ref)) {
- ParseContext parentContext = context.parent;
- object = parentContext.object;
- } else if ("$".equals(ref)) {
- ParseContext rootContext = context;
- while (rootContext.parent != null) {
- rootContext = rootContext.parent;
- }
- object = rootContext.object;
- } else {
- parser.addResolveTask(new ResolveTask(context, ref));
- parser.setResolveStatus(DefaultJSONParser.NeedToResolve);
- }
- } else {
- throw new JSONException("illegal ref, " + JSONToken.name(lexer.token()));
- }
- lexer.nextToken(JSONToken.RBRACE);
- if (lexer.token() != JSONToken.RBRACE) {
- throw new JSONException("illegal ref");
- }
- lexer.nextToken(JSONToken.COMMA);
- // parser.setContext(context, map, fieldName);
- // parser.setContext(context);
- return object;
- }
- if (map.size() == 0 //
- && lexer.token() == JSONToken.LITERAL_STRING //
- && JSON.DEFAULT_TYPE_KEY.equals(lexer.stringVal()) //
- && !lexer.isEnabled(Feature.DisableSpecialKeyDetect)) {
- lexer.nextTokenWithColon(JSONToken.LITERAL_STRING);
- lexer.nextToken(JSONToken.COMMA);
- if (lexer.token() == JSONToken.RBRACE) {
- lexer.nextToken();
- return map;
- }
- lexer.nextToken(keyDeserializer.getFastMatchToken());
- }
- Object key;
- if (lexer.token() == JSONToken.LITERAL_STRING
- && keyDeserializer instanceof JavaBeanDeserializer
- ) {
- String keyStrValue = lexer.stringVal();
- lexer.nextToken();
- DefaultJSONParser keyParser = new DefaultJSONParser(keyStrValue, parser.getConfig(), parser.getLexer().getFeatures());
- keyParser.setDateFormat(parser.getDateFomartPattern());
- key = keyDeserializer.deserialze(keyParser, keyType, null);
- } else {
- key = keyDeserializer.deserialze(parser, keyType, null);
- }
- if (lexer.token() != JSONToken.COLON) {
- throw new JSONException("syntax error, expect :, actual " + lexer.token());
- }
- lexer.nextToken(valueDeserializer.getFastMatchToken());
- Object value = valueDeserializer.deserialze(parser, valueType, key);
- parser.checkMapResolve(map, key);
- map.put(key, value);
- if (lexer.token() == JSONToken.COMMA) {
- lexer.nextToken(keyDeserializer.getFastMatchToken());
- }
- }
- } finally {
- parser.setContext(context);
- }
- return map;
- }
- public Map<Object, Object> createMap(Type type) {
- return createMap(type, JSON.DEFAULT_GENERATE_FEATURE);
- }
- @SuppressWarnings({ "unchecked", "rawtypes" })
- public Map<Object, Object> createMap(Type type, int featrues) {
- if (type == Properties.class) {
- return new Properties();
- }
- if (type == Hashtable.class) {
- return new Hashtable();
- }
- if (type == IdentityHashMap.class) {
- return new IdentityHashMap();
- }
- if (type == SortedMap.class || type == TreeMap.class) {
- return new TreeMap();
- }
- if (type == ConcurrentMap.class || type == ConcurrentHashMap.class) {
- return new ConcurrentHashMap();
- }
-
- if (type == Map.class) {
- return (featrues & Feature.OrderedField.mask) != 0
- ? new LinkedHashMap()
- : new HashMap();
- }
- if (type == HashMap.class) {
- return new HashMap();
- }
- if (type == LinkedHashMap.class) {
- return new LinkedHashMap();
- }
- if (type instanceof ParameterizedType) {
- ParameterizedType parameterizedType = (ParameterizedType) type;
- Type rawType = parameterizedType.getRawType();
- if (EnumMap.class.equals(rawType)) {
- Type[] actualArgs = parameterizedType.getActualTypeArguments();
- return new EnumMap((Class) actualArgs[0]);
- }
- return createMap(rawType, featrues);
- }
- Class<?> clazz = (Class<?>) type;
- if (clazz.isInterface()) {
- throw new JSONException("unsupport type " + type);
- }
- if ("java.util.Collections$UnmodifiableMap".equals(clazz.getName())) {
- return new HashMap();
- }
-
- try {
- return (Map<Object, Object>) clazz.newInstance();
- } catch (Exception e) {
- throw new JSONException("unsupport type " + type, e);
- }
- }
-
- public int getFastMatchToken() {
- return JSONToken.LBRACE;
- }
- }