APIJSON(八:AbstractObjectParser源码阅读(5))

APIJSON(八:AbstractObjectParser源码阅读(5))

2021SC@SDUSC

onChildParse

onChildPaerse函数主要用于解析子对象。

首先进行了isFirst和isMain的判定——

boolean isFirst = index <= 0;
boolean isMain = isFirst && type == TYPE_ITEM;

如果index索引是第一个的话,就说明是isFirst,在此基础上,如果type为TYPE_ITEM的话,就说明是isMain。

之后的话,对JSONObject的形式进行了判断——分别就Array与Object这两种形式做了不同对应的处理。

isArrayKey

if (apijson.JSONObject.isArrayKey(key)) {//APIJSON Array
   if (isMain) {
      throw new IllegalArgumentException(parentPath + "/" + key + ":{} 不合法!"
            + "数组 []:{} 中第一个 key:{} 必须是主表 TableKey:{} !不能为 arrayKey[]:{} !");
   }
   if (arrayConfig == null || arrayConfig.getPosition() == 0) {
				arrayCount ++;
				int maxArrayCount = parser.getMaxArrayCount();
				if (arrayCount > maxArrayCount) {
					throw new IllegalArgumentException(path + " 内截至 " + key + ":{} 时数组对象 key[]:{} 的数量达到 " + arrayCount + " 已超限,必须在 0-" + maxArrayCount + " 内 !");
				}
			}

首先注意到isArrayKey()这一函数——

public static boolean isArrayKey(String key) {
   return key != null && key.endsWith(KEY_ARRAY);
}

它通过key不为空及key以KEY_ARRAY结尾来进行判断,判断是否为Array的key。

之后,如果前面的isMain判定成立,就会直接报错——数组 []:{} 中第一个 key:{} 必须是主表 TableKey:{} !不能为 arrayKey[]:{} !

其次,如果arrayConfig为空或者table在[]中的位置为第一位的话,就会令arrayCount+1位,如果超出maxArrayCount(的上限),就会报错。

之后会对对象数组进行获取,并进行isEmpty的判断。

child = parser.onArrayParse(value, path, key, isSubquery);
isEmpty = child == null || ((JSONArray) child).isEmpty();

isObjectKey

else { //APIJSON Object
   boolean isTableKey = JSONRequest.isTableKey(Pair.parseEntry(key, true).getKey());
   if (type == TYPE_ITEM && isTableKey == false) {
      throw new IllegalArgumentException(parentPath + "/" + key + ":{} 不合法!"
            + "数组 []:{} 中每个 key:{} 都必须是表 TableKey:{} 或 数组 arrayKey[]:{} !");
   }

   if ( //避免使用 "test":{"Test":{}} 绕过限制,实现查询爆炸   isTableKey && 
         (arrayConfig == null || arrayConfig.getPosition() == 0)) {
      objectCount ++;
      int maxObjectCount = parser.getMaxObjectCount();
      if (objectCount > maxObjectCount) {  //TODO 这里判断是批量新增/修改,然后上限为 maxUpdateCount
         throw new IllegalArgumentException(path + " 内截至 " + key + ":{} 时对象"
               + " key:{} 的数量达到 " + objectCount + " 已超限,必须在 0-" + maxObjectCount + " 内 !");
      }
   }

如果key的类型为Object,首先会通过isTableKey函数判断是否为对应Table数组的 key。

之后,如果type不为TYPE_ITEM且,key也不是对应Table数组的,就会进行报错——数组 []:{} 中每个 key:{} 都必须是表 TableKey:{} 或 数组 arrayKey[]:{} !

之后如果key为对应Table数组的,就会进行跟上面一样的是否超出maxArrayCount(的上限)的判断。

之后会对单个对象进行获取,这里会根据isMain来确定是使用type或是使用null。

child = parser.onObjectParse(value, path, key, isMain ? arrayConfig.setType(SQLConfig.TYPE_ITEM_CHILD_0) : null, isSubquery);
isEmpty = child == null || ((JSONObject) child).isEmpty();

最后同样会进行isEmpty的判断。

if (isFirst && isEmpty) {
   invalidate();
}

同时,如果第一个就位空,就会返回无效。

最后,整个函数会根据是否为空决定返回null或是返回child即该函数所获取的对象。

return isEmpty ? null : child;

onPUTArrayParse

此函数主要用来修改数组 PUT key:[]

首先如果既不是table,array也是空的,就会不做任何处理,直接返回

if (isTable == false || array.isEmpty()) {
   Log.e(TAG, "onPUTArrayParse  isTable == false || array == null || array.isEmpty() >> return;");
   return;
}

接下来会对putType进行定义,这将会影响到之后的处理——

int putType = 0;
if (key.endsWith("+")) {//add
   putType = 1;
} else if (key.endsWith("-")) {//remove
   putType = 2;
} 

而定义的主要根据就是以什么符号结尾,值默认为0,如果是以+结尾,就会将putType置为1,如果以-结尾,就会将putType置为2.

之后会使用getRealKey()方法,获取客户端实际需要的key。

String realKey = AbstractSQLConfig.getRealKey(method, key, false, false);

之后创建了一个新的JSONObject对象,并用put方法在这里面插入了KEY_ID和KEY_COLUMN对应的键值对。

JSONObject rq = new JSONObject();
rq.put(JSONRequest.KEY_ID, request.get(JSONRequest.KEY_ID));
rq.put(JSONRequest.KEY_COLUMN, realKey);
JSONObject rp = parseResponse(RequestMethod.GET, table, null, rq, null, false);

并将rp进行parseResponse处理,即返回执行对应的sql的结果

再之后就是对targetArray进行定义,其主要就是将rp的值赋进targetArray中(针对rp为空的情况,就会创建一个空的JSONArray

JSONArray targetArray = rp == null ? null : rp.getJSONArray(realKey);
if (targetArray == null) {
   targetArray = new JSONArray();
}

Json对象中添加的是键值对,JSONArray中添加的是Json对象

之后就是针对targetArray和array做处理了

for (Object obj : array) {
   if (obj == null) {
      continue;
   }
   if (putType == 1) {
      if (targetArray.contains(obj)) {
         throw new ConflictException("PUT " + path + ", " + realKey + ":" + obj + " 已存在!");
      }
      targetArray.add(obj);
   } else if (putType == 2) {
      if (targetArray.contains(obj) == false) {
         throw new NullPointerException("PUT " + path + ", " + realKey + ":" + obj + " 不存在!");
      }
      targetArray.remove(obj);
   }
}

首先注意到for (Object obj : array)这个for循环

obj 是 Object 的一个实例对象,

整句话的意思就是,for循环array集合,这个集合,里面的对象类型是Object,取出array集合中的每个Object对象,实例化成obj小对象。然后就可以直接操作array中的这些Object类型的对象了。

jdk1.5新增迭代器for循环
(集合元素类型 局部变量 : 集合对象)
for (Object obj : collection)
将collection按顺序赋给obj,输出obj

首先,如果obj为空,就跳过。

在key是以+结尾(putType == 1)的情况下,会进行targetArray.contains的判断

contains是判断元素是否在动态数组中。

如果obj已经在targetArray中,就会报错。否则,就加入这个obj。

在key是以-结尾(putType == 2)的情况下,则刚好相反——

如果obj不在targetArray中,就会报错。否则,就移除这个obj。

程序的最后,在sqlRequest中插入(realKey, targetArray)键值对

sqlRequest.put(realKey, targetArray);

targetArray中,就会报错。否则,就加入这个obj。

在key是以-结尾(putType == 2)的情况下,则刚好相反——

如果obj不在targetArray中,就会报错。否则,就移除这个obj。

程序的最后,在sqlRequest中插入(realKey, targetArray)键值对

sqlRequest.put(realKey, targetArray);

猜你喜欢

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