/src/main/java/com/alibaba/fastjson/parser/deserializer/DefaultObjectDeserializer.java
Java | 487 lines | 452 code | 33 blank | 2 comment | 69 complexity | b9a8dd5505b0c922fec20639f0d15b3f MD5 | raw file
- package com.alibaba.fastjson.parser.deserializer;
- import java.io.Serializable;
- import java.lang.reflect.Array;
- import java.lang.reflect.GenericArrayType;
- import java.lang.reflect.Method;
- import java.lang.reflect.Modifier;
- import java.lang.reflect.ParameterizedType;
- import java.lang.reflect.Type;
- import java.lang.reflect.TypeVariable;
- import java.lang.reflect.WildcardType;
- import java.util.ArrayList;
- import java.util.HashMap;
- import java.util.IdentityHashMap;
- import java.util.List;
- import java.util.Map;
- import java.util.Properties;
- import java.util.SortedMap;
- import java.util.TreeMap;
- import java.util.concurrent.ConcurrentHashMap;
- import java.util.concurrent.ConcurrentMap;
- import com.alibaba.fastjson.JSONException;
- import com.alibaba.fastjson.parser.DefaultJSONParser;
- import com.alibaba.fastjson.parser.DefaultJSONParser.ResolveTask;
- import com.alibaba.fastjson.parser.Feature;
- import com.alibaba.fastjson.parser.JSONLexer;
- import com.alibaba.fastjson.parser.JSONScanner;
- import com.alibaba.fastjson.parser.JSONToken;
- import com.alibaba.fastjson.parser.ParseContext;
- import com.alibaba.fastjson.util.ASMClassLoader;
- import com.alibaba.fastjson.util.TypeUtils;
- public class DefaultObjectDeserializer implements ObjectDeserializer {
- public final static DefaultObjectDeserializer instance = new DefaultObjectDeserializer();
- public DefaultObjectDeserializer(){
- }
- public Object parseMap(DefaultJSONParser parser, Map<Object, Object> map, Type keyType, Type valueType,
- Object fieldName) {
- JSONScanner lexer = (JSONScanner) parser.getLexer();
- 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()) {
- Object object = null;
- lexer.nextTokenWithColon(JSONToken.LITERAL_STRING);
- if (lexer.token() == JSONToken.LITERAL_STRING) {
- String ref = lexer.stringVal();
- if ("@".equals(ref)) {
- object = context.getObject();
- } else if ("..".equals(ref)) {
- ParseContext parentContext = context.getParentContext();
- if (parentContext.getObject() != null) {
- object = parentContext.getObject();
- } else {
- parser.addResolveTask(new ResolveTask(parentContext, ref));
- parser.setResolveStatus(DefaultJSONParser.NeedToResolve);
- }
- } else if ("$".equals(ref)) {
- ParseContext rootContext = context;
- while (rootContext.getParentContext() != null) {
- rootContext = rootContext.getParentContext();
- }
- if (rootContext.getObject() != null) {
- object = rootContext.getObject();
- } else {
- parser.addResolveTask(new ResolveTask(rootContext, ref));
- parser.setResolveStatus(DefaultJSONParser.NeedToResolve);
- }
- } 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 && "@type".equals(lexer.stringVal())) {
- lexer.nextTokenWithColon(JSONToken.LITERAL_STRING);
- lexer.nextToken(JSONToken.COMMA);
- lexer.nextToken(keyDeserializer.getFastMatchToken());
- }
- Object 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);
- if (map.size() == 0 && context != null && context.getObject() != map) {
- parser.setContext(context, map, fieldName);
- }
- map.put(key, value);
- if (lexer.token() == JSONToken.COMMA) {
- lexer.nextToken(keyDeserializer.getFastMatchToken());
- }
- }
- } finally {
- parser.setContext(context);
- }
- return map;
- }
- @SuppressWarnings("rawtypes")
- public Map parseMap(DefaultJSONParser parser, Map<String, Object> map, Type valueType, Object fieldName) {
- JSONScanner lexer = (JSONScanner) parser.getLexer();
- if (lexer.token() != JSONToken.LBRACE) {
- throw new JSONException("syntax error, expect {, actual " + lexer.token());
- }
- ParseContext context = parser.getContext();
- try {
- for (;;) {
- lexer.skipWhitespace();
- char ch = lexer.getCurrent();
- if (parser.isEnabled(Feature.AllowArbitraryCommas)) {
- while (ch == ',') {
- lexer.incrementBufferPosition();
- 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.incrementBufferPosition();
- lexer.resetStringPosition();
- lexer.nextToken(JSONToken.COMMA);
- return map;
- } else if (ch == '\'') {
- if (!parser.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 (!parser.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.incrementBufferPosition();
- lexer.skipWhitespace();
- ch = lexer.getCurrent();
- lexer.resetStringPosition();
- if (key == "@type") {
- String typeName = lexer.scanSymbol(parser.getSymbolTable(), '"');
- Class<?> clazz = TypeUtils.loadClass(typeName);
- if (clazz == map.getClass()) {
- lexer.nextToken(JSONToken.COMMA);
- if (lexer.token() == JSONToken.RBRACE) {
- lexer.nextToken(JSONToken.COMMA);
- return map;
- }
- continue;
- }
- ObjectDeserializer deserializer = parser.getConfig().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 (lexer.token() == JSONToken.NULL) {
- value = null;
- lexer.nextToken();
- } else {
- value = parser.parseObject(valueType);
- }
- map.put(key, value);
- parser.checkMapResolve(map, key);
-
- parser.setContext(context, value, key);
- if (lexer.token() == JSONToken.RBRACE) {
- lexer.nextToken();
- return map;
- }
- }
- } finally {
- parser.setContext(context);
- }
- }
- public void parseObject(DefaultJSONParser parser, Object object) {
- Class<?> clazz = object.getClass();
- Map<String, FieldDeserializer> setters = parser.getConfig().getFieldDeserializers(clazz);
- JSONScanner lexer = (JSONScanner) parser.getLexer(); // xxx
- if (lexer.token() == JSONToken.RBRACE) {
- lexer.nextToken(JSONToken.COMMA);
- return;
- }
- if (lexer.token() != JSONToken.LBRACE && lexer.token() != JSONToken.COMMA) {
- throw new JSONException("syntax error, expect {, actual " + lexer.tokenName());
- }
- final Object[] args = new Object[1];
- for (;;) {
- // lexer.scanSymbol
- String key = lexer.scanSymbol(parser.getSymbolTable());
- if (key == null) {
- if (lexer.token() == JSONToken.RBRACE) {
- lexer.nextToken(JSONToken.COMMA);
- break;
- }
- if (lexer.token() == JSONToken.COMMA) {
- if (parser.isEnabled(Feature.AllowArbitraryCommas)) {
- continue;
- }
- }
- }
- FieldDeserializer fieldDeser = setters.get(key);
- if (fieldDeser == null) {
- if (!parser.isEnabled(Feature.IgnoreNotMatch)) {
- throw new JSONException("setter not found, class " + clazz.getName() + ", property " + key);
- }
- lexer.nextTokenWithColon();
- parser.parse(); // skip
- if (lexer.token() == JSONToken.RBRACE) {
- lexer.nextToken();
- return;
- }
- continue;
- } else {
- Method method = fieldDeser.getMethod();
- Class<?> fieldClass = method.getParameterTypes()[0];
- Type fieldType = method.getGenericParameterTypes()[0];
- if (fieldClass == int.class) {
- lexer.nextTokenWithColon(JSONToken.LITERAL_INT);
- args[0] = IntegerDeserializer.deserialze(parser);
- } else if (fieldClass == String.class) {
- lexer.nextTokenWithColon(JSONToken.LITERAL_STRING);
- args[0] = StringDeserializer.deserialze(parser);
- } else if (fieldClass == long.class) {
- lexer.nextTokenWithColon(JSONToken.LITERAL_INT);
- args[0] = LongDeserializer.deserialze(parser);
- } else if (fieldClass == List.class) {
- lexer.nextTokenWithColon(JSONToken.LBRACE);
- args[0] = CollectionDeserializer.instance.deserialze(parser, fieldType, null);
- } else {
- ObjectDeserializer fieldValueDeserializer = parser.getConfig().getDeserializer(fieldClass,
- fieldType);
- lexer.nextTokenWithColon(fieldValueDeserializer.getFastMatchToken());
- args[0] = fieldValueDeserializer.deserialze(parser, fieldType, null);
- }
- try {
- method.invoke(object, args);
- } catch (Exception e) {
- throw new JSONException("set proprety error, " + method.getName(), e);
- }
- }
- if (lexer.token() == JSONToken.COMMA) {
- continue;
- }
- if (lexer.token() == JSONToken.RBRACE) {
- lexer.nextToken(JSONToken.COMMA);
- return;
- }
- }
- }
- @SuppressWarnings("unchecked")
- public <T> T deserialze(DefaultJSONParser parser, Type type, Object fieldName) {
- if (type instanceof Class<?>) {
- return deserialze(parser, (Class<T>) type);
- }
- if (type instanceof ParameterizedType) {
- return (T) deserialze(parser, (ParameterizedType) type, fieldName);
- }
- if (type instanceof TypeVariable) {
- return (T) parser.parse(fieldName);
- }
- if (type instanceof WildcardType) {
- return (T) parser.parse(fieldName);
- }
-
- if (type instanceof GenericArrayType) {
- Type componentType = ((GenericArrayType) type).getGenericComponentType();
- List<Object> list = new ArrayList<Object>();
- parser.parseArray(componentType, list);
- if (componentType instanceof Class) {
- Class<?> componentClass = (Class<?>) componentType;
- Object[] array = (Object[]) Array.newInstance(componentClass, list.size());
-
- list.toArray(array);
-
- return (T) array;
- }
- }
- throw new JSONException("not support type : " + type);
- }
- @SuppressWarnings({ "rawtypes", "unchecked" })
- public <T> T deserialze(DefaultJSONParser parser, ParameterizedType type, Object fieldName) {
- try {
- JSONLexer lexer = parser.getLexer();
- if (lexer.token() == JSONToken.NULL) {
- lexer.nextToken();
- return null;
- }
- Type rawType = type.getRawType();
- if (rawType instanceof Class<?>) {
- Class<?> rawClass = (Class<?>) rawType;
- if (Map.class.isAssignableFrom(rawClass)) {
- Map map;
- if (Modifier.isAbstract(rawClass.getModifiers())) {
- if (rawClass == Map.class) {
- map = new HashMap();
- } else if (rawClass == SortedMap.class) {
- map = new TreeMap();
- } else if (rawClass == ConcurrentMap.class) {
- map = new ConcurrentHashMap();
- } else {
- throw new JSONException("can not create instance : " + rawClass);
- }
- } else {
- if (rawClass == HashMap.class) {
- map = new HashMap();
- } else {
- map = (Map) rawClass.newInstance();
- }
- }
- Type keyType = type.getActualTypeArguments()[0];
- Type valueType = type.getActualTypeArguments()[1];
- if (keyType == String.class) {
- return (T) parseMap(parser, map, valueType, fieldName);
- } else {
- return (T) parseMap(parser, map, keyType, valueType, fieldName);
- }
- }
- }
- throw new JSONException("not support type : " + type);
- } catch (JSONException e) {
- throw e;
- } catch (Throwable e) {
- throw new JSONException(e.getMessage(), e);
- }
- }
- @SuppressWarnings({ "rawtypes", "unchecked" })
- public <T> T deserialze(DefaultJSONParser parser, Class<T> clazz) {
- Object value = null;
-
- if (parser.getLexer().token() == JSONToken.NULL) {
- parser.getLexer().nextToken(JSONToken.COMMA);
- return null;
- }
- if (clazz.isAssignableFrom(HashMap.class)) {
- value = new HashMap();
- } else if (clazz.isAssignableFrom(TreeMap.class)) {
- value = new TreeMap();
- } else if (clazz.isAssignableFrom(ConcurrentHashMap.class)) {
- value = new ConcurrentHashMap();
- } else if (clazz.isAssignableFrom(Properties.class)) {
- value = new Properties();
- } else if (clazz.isAssignableFrom(IdentityHashMap.class)) {
- value = new IdentityHashMap();
- }
- if (clazz == Class.class) {
- Object classValue = parser.parse();
- if (classValue == null) {
- return null;
- }
- if (classValue instanceof String) {
- return (T) ASMClassLoader.forName((String) classValue);
- }
- } else if (clazz == Serializable.class) {
- return (T) parser.parse();
- }
- if (value == null) {
- throw new JSONException("not support type : " + clazz);
- }
- try {
- parseObject(parser, value);
- return (T) value;
- } catch (JSONException e) {
- throw e;
- } catch (Throwable e) {
- throw new JSONException(e.getMessage(), e);
- }
- }
- public int getFastMatchToken() {
- return JSONToken.LBRACE;
- }
- }