APIJSON(七:AbstractObjectParser源码阅读(4))

APIJSON(七:AbstractObjectParser源码阅读(4))

2021SC@SDUSC

onParse

key.endsWith("@")

value instanceof String

之后是如果value值是属于string类型的话——

else if (value instanceof String) { // //key{}@ getRealKey, 引用赋值路径
				String replaceKey = key.substring(0, key.length() - 1);

首先,同样是去掉最后的@符号。

String targetPath = AbstractParser.getValuePath(type == TYPE_ITEM ? path : parentPath, new String((String) value));

接下来是调用了AbstractParser中的方法getValuePath,来获取被依赖引用的key的路径, 实时替换[] -> []/i

这里其实在getValuePath中进行了一个valuePath值的判断,如果是以”/“开头的就会直接进入getAbsPath方法,获取绝对路径。否则就会进入replaceArrayChildPath方法替换[] -> []/i

Object target = onReferenceParse(targetPath);
Log.i(TAG, "onParse targetPath = " + targetPath + "; target = " + target);

将经过上面处理得到的值传入onReferenceParse方法中——

onReferenceParse方法实际上是调用了AbstractParser.getValueByPath,其主要是根据路径获取值。先取出key被valuePath包含的result,再从里面获取key对应的value,逐层到达targetKey的直接容器JSONObject parent,最后从requestObject中取值。

if (target == null) {//String#equals(null)会出错
   Log.d(TAG, "onParse  target == null  >>  return true;");
   return true;
}

这里再强调一下onParse返回值的定义。

onParse是在Parse方法中被调用用于判断其他类的数据类型。在parse函数中,如果遇到执行onParse后返回的值是false,就会直接判定为无效化。

扫描二维码关注公众号,回复: 13306120 查看本文章

这里空值null是被允许的。

if (target instanceof Map) { //target可能是从requestObject里取出的 {}
   if (isTable || targetPath.endsWith("[]/" + JSONResponse.KEY_INFO) == false) {
      Log.d(TAG, "onParse  target instanceof Map  >>  return false;");
      return false; 
   }
}

如果target的值属于Map型,且不为表格同时也不是以[]/+info(详细分页信息)结尾的话,就会被判定为无效化。这里如此做的原因是防止二次遍历再解析。

if (targetPath.equals(target)) {
   Log.d(TAG, "onParse  targetPath.equals(target)  >>");

   //非查询关键词 @key 不影响查询,直接跳过
   if (isTable && (key.startsWith("@") == false || JSONRequest.TABLE_KEY_LIST.contains(key))) {
      Log.e(TAG, "onParse  isTable && (key.startsWith(@) == false"
            + " || JSONRequest.TABLE_KEY_LIST.contains(key)) >>  return null;");
      return false;//获取不到就不用再做无效的query了。不考虑 Table:{Table:{}}嵌套
   } else {
      Log.d(TAG, "onParse  isTable(table) == false >> return true;");
      return true;//舍去,对Table无影响
   }
} 

经过上述对target的值的先行判断,现在来到第二类判断——targetPath与target是否相等,即valuePath和保证getValueByPath传进去的值是否一致。在一致的情况下,如果istable或key不以@开头且TABLE_KEY_LIST中不包含key,则会被判定为无效。

此外,则是通过判定的,即返回值为true。

Log.i(TAG, "onParse    >>  key = replaceKey; value = target;");
key = replaceKey;
value = target;
Log.d(TAG, "onParse key = " + key + "; value = " + value);

如果targetPath与target不相等,就会进入最后的赋值,直接替换原来的key@:path为key:target。

else

else {
   throw new IllegalArgumentException(path + "/" + key + ":value 中 value 必须为 依赖路径String 或 SQL子查询JSONObject !");
}

即如果在key以@结尾,而value值既不为JSONObject也不为String类型时,就会抛出异常。

key.endsWith("()")

value instanceof String == false

会直接抛出异常——

if (value instanceof String == false) {
   throw new IllegalArgumentException(path + "/" + key + ":value 中 value 必须为函数String!");
}

value 中 value 必须为函数String

else

老样子,首先去掉末尾的()

String k = key.substring(0, key.length() - 2);

下面会进行type的判断,并根据type的类型,做不同的解析策略

远程函数

{"-":{ “key-()”:value }, “0”:{ “key()”:value }, “+”:{ “key+()”:value } }

-: 在executeSQL前解析

0 : 在executeSQL后、onChildParse前解析

+: 在onChildParse后解析

然后是进行一个去掉末尾的value后(k)是否以"—"(减号)结尾的判断

如果是以减号结尾的,给type赋值,然后去掉减号。

if (isMinus) { //不能封装到functionMap后批量执行,否则会导致非Table内的 key-():function() 在onChildParse后执行!
   type = "-";
   k = k.substring(0, k.length() - 1);

   if (isTable == false) {
      parseFunction(k, (String) value, parentPath, name, request);
   }
}

之后会进行一个isTable的判断

以下是parseFunction的相关内容

public void parseFunction(String key, String value, String parentPath, String currentName, JSONObject currentObject) throws Exception {
   Object result;
   if (key.startsWith("@")) {
      FunctionBean fb = AbstractFunctionParser.parseFunction(value, currentObject, true);

      SQLConfig config = newSQLConfig(true);
      config.setProcedure(fb.toFunctionCallString(true));
      result = parseResponse(config, true);

      key = key.substring(1);
   }
   else {
      result = parser.onFunctionParse(key, value, parentPath, currentName, currentObject);
   }

   if (result != null) {
      String k = AbstractSQLConfig.getRealKey(method, key, false, false);

      response.put(k, result);
      parser.putQueryResult(AbstractParser.getAbsPath(path, k), result);
   }
}

主要还是针对key和result的不同类型进行解析。

下一种类型是k以加号结尾,这里就是简单的给type赋上对应的值后,削去最后的+

else if (k.endsWith("+")) {
   type = "+";
   k = k.substring(0, k.length() - 1);
}

最后就是type="0"了

else {
   type = "0";
}

之后就是如果不以减号结尾或者是表格的情况——

if (isMinus == false || isTable) {
   //远程函数比较少用,一般一个Table:{}内用到也就一两个,所以这里循环里new出来对性能影响不大。
   Map<String, String> map = functionMap.get(type);
   if (map == null) {
      map = new LinkedHashMap<>();
   }
   map.put(k, (String) value);

   functionMap.put(type, map);
}

这里是首先创建了一个map,然后把赋上k和value值,最后再赋回functionMap

put()函数
V put(K key, V value)
**使用的参数:**该方法有两个参数。
key - 与指定值相关联的键。
value - 与指定键关联的值。

**返回值:**当存在这个key的时候,会覆盖掉原来的value并返回oldvalue,也就是旧值。

对返回值的进一步解释:
如果没有键映射,则返回NULL。
该函数返回与指定键关联的旧值。
这个操作不管啥条件都会覆盖旧的。

get(key):
使用的参数:
Key - 其关联值将被返回的键。

**返回值:**指定键映射到的值,如果此映射不包含键的映射,则为NULL。

返回值进一步阐述:
使用get函数,那么应该有先调用put函数对m表进行存储,不然肯定是返回null;
由于m表的存储跟put函数有关,在实际工程应用中get返回值是受到put函数影响的。

如果isTable且key以@开始且TABLE_KEY_LIST中不包含key

else if (isTable && key.startsWith("@") && JSONRequest.TABLE_KEY_LIST.contains(key) == false) {
   customMap.put(key, value);
}

就会在customMap中插入value值

最后所有的前面未执行的都会在sqlRequest中插入

else {
   sqlRequest.put(key, value);
}

没有任何错误的走回上述流程,就是return true了

return true;
ains(key) == false) {
   customMap.put(key, value);
}

就会在customMap中插入value值

最后所有的前面未执行的都会在sqlRequest中插入

else {
   sqlRequest.put(key, value);
}

没有任何错误的走回上述流程,就是return true了

return true;

猜你喜欢

转载自blog.csdn.net/qq_50861917/article/details/121325078