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,就会直接判定为无效化。
这里空值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;