Tencent/APIJSON

一个json(事务)同时支持新增、修改、删除、查询、别名

cloudAndMonkey opened this issue · 84 comments

版本5.2.0
1、业务表-插入不同表1:1、1:n、n:n
2、业务表-修改不同表1:1、1:n、n:n
3、业务表-批量删除不同表
实现流程:
1、继承APIJSONParser
2、重载 parseCorrectRequest方法
User__User 通过__分割, tag 和 structure的类名
新增, tag和 structure的类名一样, 更多示例请参见postman
image
image
image
该方法,是参数校验入口
image
特定tag,则走分支流程
image
image
修改引用关系
image
postman测试示例:
业务表-插入不同表1:1-源码实现

{
    "User__User":{
        "username":"test2",
        "password": "123456",
		"state": 1
    },
    "User_address__User_address": 
	{
	"user_id@": "User/id",
	"addr": "ddd",
	"count": 1
	},
    "tag": "Batch_Tag_UserWithUser_addressList"
}

业务表-插入不同表1:n-源码实现

{
    "User__User":{
        "username":"test1",
        "password": "123456",
		"state": 1
    },
    "User_address[]__User_address[]": [
    	{
    	"user_id@": "User/id",
    	"addr": "ddd",
    	"count": 1
    	},
    	{
    	"user_id@": "User/id",
    	"addr": "ddd1",
    	"count": 2
    	}
    ],
    "tag": "Batch_Tag_UserWithUser_addressList"
}

业务表-插入不同表n:n-源码实现

{
    "User[]__User[]":[
    	{
        "username":"test3",
        "password": "123456",
		"state": 1
    	},
    	{
        "username":"test4",
        "password": "123456",
		"state": 1
    	}
    ],
    "User_address[]__User_address[]": [
    	{
    	"user_id": "94593122-403a-4eb2-a6f0-182ed3da7764",
    	"addr": "ddd",
    	"count": 1
    	},
    	{
    	"user_id": "94593122-403a-4eb2-a6f0-182ed3da7764",
    	"addr": "ddd1",
    	"count": 2
    	}
    ],
    "tag": "Batch_Tag_UserWithUser_addressList"
}

业务表-批量修改不同表1:n-源码实现

{
    "User__User":{
    	"id": "94593122-403a-4eb2-a6f0-182ed3da7764",
        "username":"test1-1",
        "password": "111111",
		"state": 1
    },
    "User_address[]__User_address[]": [
    	{
    	"id": "e8bb9e79-9bbe-49d2-9542-77792368bece",
    	"user_id@": "User/id",
    	"addr": "addr-01",
    	"count": 1
    	},
    	{
    	"id": "4dfee57f-6953-4371-865f-22b6e1957fee",
    	"user_id@": "User/id",
    	"addr": "addr-11",
    	"count": 1
    	}
    ],
    "tag": "Batch_Tag_UserWithUser_addressList"
}

业务表-批量修改不同表n:n-源码实现

{
    "User[]__User[]":[
    	{
    	"id": "f60e829a-1181-4331-ac1e-f5faf64e3a8c",
        "username":"test-3",
        "password": "123456-1",
		"state": 1
    	},
    	{
    	"id": "ca86a2e0-d504-4772-b06a-1a8c9e2b12c9",
        "username":"test-4",
        "password": "123456-1",
		"state": 1
    	}
    ],
    "User_address[]__User_address[]": [
    	{
    	"id": "faf8a605-66a3-4ce1-b774-c499b86a4984",
    	"user_id": "94593122-403a-4eb2-a6f0-182ed3da7764",
    	"addr": "ddd-1",
    	"count": 1
    	},
    	{
    	"id": "ac88ce16-6cdf-41a3-b382-c78452c5a850",
    	"user_id": "94593122-403a-4eb2-a6f0-182ed3da7764",
    	"addr": "ddd-2",
    	"count": 2
    	}
    ],
    "tag": "Batch_Tag_UserWithUser_addressList"
}

业务表-批量删除不同表-源码实现

{
    "User[]__User":{
    	"id{}": ["8e44c04a-6e90-4dfe-b021-3436453c55dd", "94593122-403a-4eb2-a6f0-182ed3da7764","ca86a2e0-d504-4772-b06a-1a8c9e2b12c9"]
    },
    "User_address[]__User_address": {
    	"id{}": ["1ed2dda1-5800-4b69-b128-7771dd79046f", "e8bb9e79-9bbe-49d2-9542-77792368bece","4dfee57f-6953-4371-865f-22b6e1957fee","faf8a605-66a3-4ce1-b774-c499b86a4984"]
    },
    "tag": "Batch_Tag_UserWithUser_addressList"
}

后续我再研究一下
1、支持不同的操作类型,比如 GET、POST、DELETE, 在一个json里面, 才能保证事物
2、function函数 执行语句, 加入事物
框架能支持数组, 把数组拆解为一条一条语句执行, 只要把相关引用 传递进 function应该能搞定,空了研究一下,哈哈

赞,感谢分享~

把增删改查不同操作放在一个请求 JSON 中,需要额外字段来标记,例如可以是

{
   "Moment": {
     "@method": "POST",
     // TODO 其它字段
   },
   "Comment[]": [
      {
        "@method": "PUT",
        // TODO 其它字段
      }
   ]
}

或者这样更好一些,可以提前知道那些片段属于哪种操作,方便解析,性能也更好:

{
   "@post": "Moment,Comment[]", // 分发到 POST 请求对应的解析处理
   "Moment": {
     // TODO 其它字段
   },
   "Comment[]": [
      {
        // TODO 其它字段
      }
   ],
   "@get": "User", // 分发到 GET 请求对应的解析处理
   "User": {
     // TODO 其它字段
   },
   "Privacy": { // 按 URL 对应的默认方法处理
     // TODO 其它字段
   }
}

对于没有显式声明操作方法的,直接用 URL(/get, /post 等) 对应的默认操作方法

@TommyLemon >
临时变量 是以表名为维度
"@post": "Moment,Comment[]", 解决不了同时操作一张表
比如
sys_permission 菜单表
新增一条记录, 要修改父菜单的is_leaf(是否叶子节点:1:是 0:不是)

流程要处理几个地方(还没有细化):
1、校验
2、语句执行
语句执行的地方要能区分一张表不同的 请求操作类型

还有一种方法, 通过request structure 字段来支持,通过json格式匹配
1、校验
{
"post":
[
{"Table_order_list_test": {"MUST":"aa,dd","UPDATE": {"@ROLE": "OWNER,ADMIN","pwdEncrypt-()": "pwdEncrypt(id,password)"}, "REFUSE": "id"}},
{"User[]": {"User[]": [{"MUST":"username,password","REFUSE": "id"}], "UPDATE": {"@ROLE": "OWNER,ADMIN"}}}
]
"put":
[
{"Table_order_list_test": {"MUST":"aa,dd","UPDATE": {"@ROLE": "OWNER,ADMIN","pwdEncrypt-()": "pwdEncrypt(id,password)"}, "REFUSE": "id"}},
{"User[]": {"User[]": [{"MUST":"username,password","REFUSE": "id"}], "UPDATE": {"@ROLE": "OWNER,ADMIN"}}}
]
}
2、语句执行
@post@get 如何打到对象上面跟着语句走

目前我能想到比较简单的方式:
key: tag-table-post
语句执行
再想办法将 @post@get 如何打到对象上面跟着语句走

@TommyLemon > 临时变量 是以表名为维度 "@post": "Moment,Comment[]", 解决不了同时操作一张表 比如 sys_permission 菜单表 新增一条记录, 要修改父菜单的is_leaf(是否叶子节点:1:是 0:不是)

流程要处理几个地方(还没有细化): 1、校验 2、语句执行 语句执行的地方要能区分一张表不同的 请求操作类型

对同一张表可以用别名来区分不同记录,例如:

{
  "User": {
     //TODO 其它字段
  },
  "User:owner": {
    "@role": "OWNER",
     //TODO 其它字段
  },
  "User:count": {
    "@column": "count(1)",
     //TODO 其它字段
  }
}

具体见 通用文档 > 3.设计规范 > 3.2 功能符 > 新建别名
https://github.com/Tencent/APIJSON/blob/master/Document.md#3.2

@TommyLemon >
"name:alias",name映射为alias,用alias替代name。可用于 column,Table,SQL函数 等。只用于GET类型、HEAD类型的请求
post请求, 没办法传递 别名呀
{
"User:aa":{
"username":"test",
"password": "233223",
"state": 1
},
"tag": "User"
}

{"User:aa":{"username":"test","password":"233223","state":1},"format":true}
java.lang.UnsupportedOperationException: POST请求,请在 内传 User:{} !

以前没有这样的需求,现在可以新增支持。
”POST请求,请在 内传 User:{} !“
这个报错是因为 Request 表 structure 中配置的就是 "User":{} 而不是 "User:aa":{}

以前没有这样的需求,现在可以新增支持。 ”POST请求,请在 内传 User:{} !“ 这个报错是因为 Request 表 structure 中配置的就是 "User":{} 而不是 "User:aa":{}

嗯嗯,功能我基本调通了,一些细节我还要调整一下,比如 第一条语句 查询 如果没有结果,将会直接返回 等等

以前没有这样的需求,现在可以新增支持。 ”POST请求,请在 内传 User:{} !“ 这个报错是因为 Request 表 structure 中配置的就是 "User":{} 而不是 "User:aa":{}
@TommyLemon
单表新增、修改、删除支持别名 #470

@TommyLemon
一个json 支持新增(单条、批量)、修改(单条、批量)、删除、查询、别名
实现代码如下:
1、重载 APIJSONParser 实现 parseCorrectRequest
2、注释tag校验
image
3、FormParser
实现单条、批量校验逻辑
`/**
* 相同对象,通过别名区分
* @param method
* @param tag
* @param version
* @param name
* @param request
* @param maxUpdateCount
* @param creator
* @return
* @throws Exception
*/
private JSONObject batchVerify(RequestMethod method, String tag, int version, String name,
@NotNull JSONObject request, int maxUpdateCount, SQLCreator creator) throws Exception {
JSONObject jsonObject = new JSONObject(true);
String _tag = null;
if (request.keySet() == null || request.keySet().size() == 0) {
throw new IllegalArgumentException("json对象格式不正确 !,例如 "User": {}");
}
for (String key : request.keySet()) {
// key重复直接抛错
if (jsonObject.containsKey(key)) {
throw new IllegalArgumentException("json对象名重复,请添加操作类型区分!,例如 method__tag__structureKey, 或者: tag__structureKey");
}

		if(key.startsWith("@") || key.endsWith("@")) {
			jsonObject.put(key, request.get(key));
			continue;
		}
		
		// 处理别名
		if(request.get(key) instanceof JSONObject || request.get(key) instanceof JSONArray) {
			String tmpKey = key;
			if(apijson.JSONObject.isTableArray(key)) {
				tmpKey = (key.substring(0, key.length() - apijson.JSONObject.KEY_ARRAY.length()));
			}
			if(tableAlias.get(tmpKey) == null) {
				int keyIndex = tmpKey.indexOf(":");
				if(keyIndex != -1) {
					tableAlias.put(tmpKey, tmpKey.substring(0, keyIndex));
				}
			}
		}
		
		// 获取执行方法
		if (request.get(key) instanceof JSONObject) {
			String _method = request.getJSONObject(key).getString("@method");
			if(_method != null) {
				method = RequestMethod.valueOf(_method.toUpperCase());
			}
			
			// 判断是否为get请求
			if (RequestMethod.isPublicMethod(method)) {
				jsonObject.put(key, request.getJSONObject(key));
				continue;
			}
			// 非get请求,则进行参数校验
			String tmpTag = request.getJSONObject(key).getString("@tag");
			if(tmpTag != null) {
				_tag = tmpTag;
			}else if(StringUtil.isEmpty(tag)) {
				// 批量操作 tag[] = key[]
				if(apijson.JSONObject.isTableArray(key)) {
					String tmpKey = (key.substring(0, key.length() - apijson.JSONObject.KEY_ARRAY.length()));
					if(tableAlias.get(tmpKey) != null) {
						_tag = tableAlias.get(tmpKey) + apijson.JSONObject.KEY_ARRAY;
					}else {
						// 不存在别名
						_tag = key;
					}
				}else {
					// 单条操作, tag = key
					if(tableAlias.get(key) != null) {
						_tag = tableAlias.get(key);
					}else {
						// 不存在别名
						_tag = key;
					}
				}
			}else {
				// 数组解析成对象,会进入
				if(tableAlias.get(tag) != null) {
					_tag = tableAlias.get(tag);
				}else {
					_tag = tag;
				}
			}
			JSONObject requestItem = new JSONObject();
			requestItem.put(_tag, request.get(key));
			JSONObject object = getLocalStructure(method, _tag, version);
			JSONObject ret = commonVerify(method, _tag, version, name, requestItem, maxUpdateCount, creator, object);
			jsonObject.put(key, ret.getJSONObject(_tag));
		}else if(request.get(key) instanceof JSONArray) {
            jsonObject.put(key, request.getJSONArray(key));
		}else {
			jsonObject.put(key, request.get(key));
		}
	}

	return jsonObject;
}`

4、修改 AbstractParser
image
image
示例:
sql层级最多5层
// 新增、修改、删除
// 执行sql语句条数不能超过5条
{
"User:aa":{
"@method": "POST",
"username":"test1",
"password": "123456",
"state": 1
},
"User_address[]": [
{
"@method": "POST",
"user_id@": "User:aa/id",
"addr": "ddd",
"count": 1
},
{
"@method": "POST",
"user_id@": "User:aa/id",
"addr": "ddd1",
"count": 2
}
],
"User_address:modifUA":
{
"@method": "PUT",
"id": "1c051f08-4671-4fef-8ae3-64fc8b45047d",
"user_id@": "User:aa/id",
"addr": "addr-01",
"count": 1
},
"User:delUser":{
"@method": "DELETE",
"id{}": ["1d42c09c-0780-4762-8100-a718d7c8a83b", "a1d51e2a-797c-4b3f-afc4-45befcd775ed"]
},
"@Explain": true
}
image
// 新增、修改、删除、查询
// get请求会导致事物无法提交(看需要是否支持)
// get请求最好放到前置函数里面操作,通过前置函数来回填需要新增、修改的参数
{
"User:aa":{
"@method": "POST",
"username":"test1",
"password": "123456",
"state": 1
},
"User_address[]": [
{
"@method": "POST",
"user_id@": "User:aa/id",
"addr": "ddd",
"count": 1
},
{
"@method": "POST",
"user_id@": "User:aa/id",
"addr": "ddd1",
"count": 2
}
],
"sql@": {
"@method": "GET",
"with": true,
"from": "User",
"User": {
"@column": "id",
"id{}": ["834df81e-cf8b-40a5-9638-c62fb00e8db4"]
}
},
"User_address:sUA[]": {
"@method": "GET",
"User_address": {
"user_id{}@": "sql"
},
"page": 0,
"count": 10,
"query": 2
},
"total@": "/User_address:sUA[]/total",
"@Explain": true
}
多条查询:
{
"sql@": {
"@method": "GET",
"with": true,
"from": "User",
"User": {
"@column": "id",
"id{}": ["64c09bdc-927a-411b-843f-ff3f72b5d5be"]
}
},
"User_address:ua[]": {
"@method": "GET",
"User_address": {
"user_id{}@": "sql"
},
"page": 0,
"count": 10,
"query": 2
},
"total@": "/User_address:ua[]/total",
"sql1@": {
"@method": "GET",
"with": true,
"from": "User",
"User": {
"@column": "id",
"id{}": ["64c09bdc-927a-411b-843f-ff3f72b5d5be"]
}
},
"User_address:ua1[]": {
"@method": "GET",
"User_address": {
"user_id{}@": "sql1"
},
"page": 0,
"count": 10,
"query": 2
},
"total1@": "/User_address:ua1[]/total",
"@Explain": true
}

@TommyLemon 一个json 支持新增(单条、批量)、修改(单条、批量)、删除、查询、别名 实现代码如下: 1、重载 APIJSONParser 实现 parseCorrectRequest 2、注释tag校验 image 3、FormParser 实现单条、批量校验逻辑 /** * 相同对象,通过别名区分 * @param method * @param tag * @param version * @param name * @param request * @param maxUpdateCount * @param creator * @return * @throws Exception */ private JSONObject batchVerify(RequestMethod method, String tag, int version, String name, @NotNull JSONObject request, int maxUpdateCount, SQLCreator creator) throws Exception { JSONObject jsonObject = new JSONObject(true); String _tag = null; if (request.keySet() == null || request.keySet().size() == 0) { throw new IllegalArgumentException("json对象格式不正确 !,例如 "User": {}"); } for (String key : request.keySet()) { // key重复直接抛错 if (jsonObject.containsKey(key)) { throw new IllegalArgumentException("json对象名重复,请添加操作类型区分!,例如 method__tag__structureKey, 或者: tag__structureKey"); }

		if(key.startsWith("@") || key.endsWith("@")) {
			jsonObject.put(key, request.get(key));
			continue;
		}
		
		// 处理别名
		if(request.get(key) instanceof JSONObject || request.get(key) instanceof JSONArray) {
			String tmpKey = key;
			if(apijson.JSONObject.isTableArray(key)) {
				tmpKey = (key.substring(0, key.length() - apijson.JSONObject.KEY_ARRAY.length()));
			}
			if(tableAlias.get(tmpKey) == null) {
				int keyIndex = tmpKey.indexOf(":");
				if(keyIndex != -1) {
					tableAlias.put(tmpKey, tmpKey.substring(0, keyIndex));
				}
			}
		}
		
		// 获取执行方法
		if (request.get(key) instanceof JSONObject) {
			String _method = request.getJSONObject(key).getString("@method");
			if(_method != null) {
				method = RequestMethod.valueOf(_method.toUpperCase());
			}
			
			// 判断是否为get请求
			if (RequestMethod.isPublicMethod(method)) {
				jsonObject.put(key, request.getJSONObject(key));
				continue;
			}
			// 非get请求,则进行参数校验
			String tmpTag = request.getJSONObject(key).getString("@tag");
			if(tmpTag != null) {
				_tag = tmpTag;
			}else if(StringUtil.isEmpty(tag)) {
				// 批量操作 tag[] = key[]
				if(apijson.JSONObject.isTableArray(key)) {
					String tmpKey = (key.substring(0, key.length() - apijson.JSONObject.KEY_ARRAY.length()));
					if(tableAlias.get(tmpKey) != null) {
						_tag = tableAlias.get(tmpKey) + apijson.JSONObject.KEY_ARRAY;
					}else {
						// 不存在别名
						_tag = key;
					}
				}else {
					// 单条操作, tag = key
					if(tableAlias.get(key) != null) {
						_tag = tableAlias.get(key);
					}else {
						// 不存在别名
						_tag = key;
					}
				}
			}else {
				// 数组解析成对象,会进入
				if(tableAlias.get(tag) != null) {
					_tag = tableAlias.get(tag);
				}else {
					_tag = tag;
				}
			}
			JSONObject requestItem = new JSONObject();
			requestItem.put(_tag, request.get(key));
			JSONObject object = getLocalStructure(method, _tag, version);
			JSONObject ret = commonVerify(method, _tag, version, name, requestItem, maxUpdateCount, creator, object);
			jsonObject.put(key, ret.getJSONObject(_tag));
		}else if(request.get(key) instanceof JSONArray) {
            jsonObject.put(key, request.getJSONArray(key));
		}else {
			jsonObject.put(key, request.get(key));
		}
	}

	return jsonObject;
}

4、修改 AbstractParser image image 示例: sql层级最多5层 // 新增、修改、删除 // 执行sql语句条数不能超过5条 { "User:aa":{ "@method": "post", "username":"test1", "password": "123456", "state": 1 }, "User_address[]": [ { "@method": "post", "user_id@": "User:aa/id", "addr": "ddd", "count": 1 }, { "@method": "post", "user_id@": "User:aa/id", "addr": "ddd1", "count": 2 } ], "User_address:modifUA": { "@method": "put", "id": "1c051f08-4671-4fef-8ae3-64fc8b45047d", "user_id@": "User:aa/id", "addr": "addr-01", "count": 1 }, "User:delUser":{ "@method": "delete", "id{}": ["1d42c09c-0780-4762-8100-a718d7c8a83b", "a1d51e2a-797c-4b3f-afc4-45befcd775ed"] }, "@Explain": true } image // 新增、修改、删除、查询 // get请求会导致事物无法提交(看需要是否支持) // get请求最好放到前置函数里面操作,通过前置函数来回填需要新增、修改的参数 { "User:aa":{ "@method": "post", "username":"test1", "password": "123456", "state": 1 }, "User_address[]": [ { "@method": "post", "user_id@": "User:aa/id", "addr": "ddd", "count": 1 }, { "@method": "post", "user_id@": "User:aa/id", "addr": "ddd1", "count": 2 } ], "sql@": { "@method": "get", "with": true, "from": "User", "User": { "@column": "id", "id{}": ["834df81e-cf8b-40a5-9638-c62fb00e8db4"] } }, "User_address:sUA[]": { "@method": "get", "User_address": { "user_id{}@": "sql" }, "page": 0, "count": 10, "query": 2 }, "total@": "/User_address:sUA[]/total", "@Explain": true } 多条查询: { "sql@": { "@method": "get", "with": true, "from": "User", "User": { "@column": "id", "id{}": ["64c09bdc-927a-411b-843f-ff3f72b5d5be"] } }, "User_address:ua[]": { "@method": "get", "User_address": { "user_id{}@": "sql" }, "page": 0, "count": 10, "query": 2 }, "total@": "/User_address:ua[]/total", "sql1@": { "@method": "get", "with": true, "from": "User", "User": { "@column": "id", "id{}": ["64c09bdc-927a-411b-843f-ff3f72b5d5be"] } }, "User_address:ua1[]": { "@method": "get", "User_address": { "user_id{}@": "sql1" }, "page": 0, "count": 10, "query": 2 }, "total1@": "/User_address:ua1[]/total", "@Explain": true }

赞,感谢分享~

可以最外层新增传参
"transaction": true
来指定有事务,这个全局关键词目前未支持,需要自己实现下。
然后重写 Parser 中
setAutoCommit
begin
commit
rollback
等事务相关方法。

另外建议 @method 值用全大写,例如 "@method": "GET",保持统一的常量/关键词命名风格,也方便复用 enum RequestMethod,例如
RequestMethod.GET.name().equals(method)
或者
RequestMethod.valueOf(method)

可以最外层新增传参 "transaction": true 来指定有事务,这个全局关键词目前未支持,需要自己实现下。 然后重写 Parser 中 setAutoCommit begin commit rollback 等事务相关方法。

另外建议 @method 值用全大写,例如 "@method": "GET",保持统一的常量/关键词命名风格,也方便复用 enum RequestMethod,例如 RequestMethod.GET.name().equals(method) 或者 RequestMethod.valueOf(method)

好的,谢谢

可以最外层新增传参 "transaction": true 来指定有事务,这个全局关键词目前未支持,需要自己实现下。 然后重写 Parser 中 setAutoCommit begin commit rollback 等事务相关方法。

另外建议 @method 值用全大写,例如 "@method": "GET",保持统一的常量/关键词命名风格,也方便复用 enum RequestMethod,例如 RequestMethod.GET.name().equals(method) 或者 RequestMethod.valueOf(method)

@TommyLemon
json第一次执行,会设置 AbstractSQLExecutor transactionIsolation , GET = 0 , 其他= 4
image

json解析每一条语句执行,只会改变自己的 transactionIsolation
image
所以只需要在 AbstractParser onCommit 这里改变判断条件即可:
以前是 get请求直接返回,不执行 commit
image
测试示例: 查询、新增

{
    "sql@": {
    	"@method": "GET",
        "with": true,
        "from": "User",
        "User": {
          "@column": "id",
          "id{}": ["c692d9d1-2e23-4055-99fb-66461bda33c3"]
        }
    },
    "User_address:uad[]": {
    	"@method": "GET",
        "User_address": {
            "user_id{}@": "sql"
        },
        "page": 0,
        "count": 10,
        "query": 2
    },
    "total@": "/User_address:uad[]/total",
   "User:aa":{
   		"@method": "POST",
        "username":"test1",
        "password": "123456",
		"state": 1
    },
    "User_address:uad1[]": [
    	{
    	"@method": "POST",
    	"user_id@": "User:aa/id",
    	"addr": "ddd",
    	"count": 1
    	},
    	{
    	"@method": "POST",
    	"user_id@": "User:aa/id",
    	"addr": "ddd1",
    	"count": 2
    	}
    ],
    
    "@explain": true
}

执行结果: 事务生效, 数据入库正常
image

你把 WITH(SELECT ...) AS `sql` 也实现了嘛?
https://github.com/Tencent/APIJSON/blob/master/Roadmap.md
image

你把 WITH(SELECT ...) AS sql 也实现了嘛? https://github.com/Tencent/APIJSON/blob/master/Roadmap.md image

好的,我先看看

我还要稍微调一下
确认一下, 只有GET 查询 使用 with-as表达式吗?
子查询 删除/修改 采用 in的方式?
还是统一都采用with-as表达式?

@TommyLemon
apijson版本: 5.4
mysql8 支持 with as表达式, 提高性能
实现流程图:
image

修改源码: AbstractSQLConfig
image
image
测试用例:
// 测试 mysql8 with as表达式
// 用户表
// 用户角色表
// 角色表
// 示例一 单个range ref引用
{
"sql@": {
"@method": "GET",
"with": true,
"from": "Sys_role",
"Sys_role": {
"@column": "id",
"role_name": "角色1"
}
},
"Sys_user_role:sur[]": {
"@method": "GET",
"Sys_user_role": {
"role_id{}@": "sql"
}
},
"Sys_role_permission:srp[]": {
"@method": "GET",
"Sys_role_permission": {
"role_id{}@": "sql"
}
},
"@Explain": true
}
image
mysql5.7执行结果:
image
场景二 多个range ref引用
{
"sql@": {
"@method": "GET",
"with": true,
"from": "Sys_role",
"Sys_role": {
"@column": "id",
"role_name": "角色1"
}
},
"sql_user@": {
"@method": "GET",
"with": true,
"from": "Sys_user",
"Sys_user": {
"@column": "id",
"id": "f0894db2-6940-4d89-a5b2-4405d0ad0c8f"
}
},
"Sys_user_role:sur[]": {
"@method": "GET",
"Sys_user_role": {
"role_id{}@": "sql",
"user_id{}@": "sql_user"
}
},
"Sys_role_permission:srp[]": {
"@method": "GET",
"Sys_role_permission": {
"role_id{}@": "sql"
}
},
"@Explain": true
}
image
mysql5.7执行结果:
image
经过相关功能点复测,不影响其他功能点 :
新增、修改、删除、(一个json包含新增、修改、删除)
例如(不想看可以忽略,举一个复杂测试示例):
{
"sql@": {
"@method": "GET",
"with": true,
"from": "Sys_role",
"Sys_role": {
"@column": "id",
"role_name": "角色1"
}
},
"sql_user@": {
"@method": "GET",
"with": true,
"from": "Sys_user",
"Sys_user": {
"@column": "id",
"id": "f0894db2-6940-4d89-a5b2-4405d0ad0c8f"
}
},
"Sys_user_role:sur[]": {
"@method": "GET",
"Sys_user_role": {
"role_id{}@": "sql",
"user_id{}@": "sql_user"
}
},
"Sys_role_permission:srp[]": {
"@method": "GET",
"Sys_role_permission": {
"role_id{}@": "sql"
}
},
"Sys_user:sy":{
"@method": "POST",
"username":"test-4",
"password": "123456",
"status": 1
},
"Sys_role:sr":
{
"@method": "POST",
"role_name": "角色-4",
"role_code": "1111-4",
"description": "角色-4"
},
"Sys_user_role:sur":{
"@method": "POST",
"user_id@": "Sys_user:sy/id",
"role_id@": "Sys_role:sr/id"
},
"@Explain": true
}
image
image

起码 GET 和 GETS 都支持,可以用 RequestMethod.isGetMethod(method, true) 判断;
还可以也支持 HEAD 和 HEADS,可以用 RequestMethod.isPublicMethod(method, true) 判断。

至于 PUT, DELETE 也可以支持,那就是只要 method != RequestMethod.POST 就都支持,
方便实现根据特定子查询条件来修改/删除数据。

起码 GET 和 GETS 都支持,可以用 RequestMethod.isGetMethod(method, true) 判断; 还可以也支持 HEAD 和 HEADS,可以用 RequestMethod.isPublicMethod(method, true) 判断。

至于 PUT, DELETE 也可以支持,那就是只要 method != RequestMethod.POST 就都支持, 方便实现根据特定子查询条件来修改/删除数据。
@TommyLemon
这几种method 我都搞定了
image

我再测一下, 确认没啥问题, 再提PR
测得我两眼冒金花了
这段时间搞下来, 开源、持续维护、功能版本迭代真不容易呀,能坚持下来都是神人, 哈哈😄

目前已经完成的功能点:
1、delete 非id 、ref引用
2、json(事物) 同时支持新增、修改、删除、查询、别名
3、别名
4、with-as支持

起码 GET 和 GETS 都支持,可以用 RequestMethod.isGetMethod(method, true) 判断; 还可以也支持 HEAD 和 HEADS,可以用 RequestMethod.isPublicMethod(method, true) 判断。
至于 PUT, DELETE 也可以支持,那就是只要 method != RequestMethod.POST 就都支持, 方便实现根据特定子查询条件来修改/删除数据。
@TommyLemon
这几种method 我都搞定了
image

我再测一下, 确认没啥问题, 再提PR 测得我两眼冒金花了 这段时间搞下来, 开源、持续维护、功能版本迭代真不容易呀,能坚持下来都是神人, 哈哈😄

目前已经完成的功能点: 1、delete 非id 、ref引用 2、json(事物) 同时支持新增、修改、删除、查询、别名 3、别名 4、with-as支持

@cloudAndMonkey 赞,感谢,期待 PR~
现有功能推荐用 APIAuto 来零代码回归测试,新增功能也可以添加测试 Demo 到 APIAuto
https://github.com/TommyLemon/APIAuto

image

还可以额外配置请求参数生成规则
image

image

@TommyLemon
apijson版本: 5.4
head 子查询,不会经过校验 ,会将 sql@ 解析为 count(xx)执行, 这是一个bug
image
目前我是通过 "@method": "GET", 来控制的,你看是否需要调整?
{
"sql@": {
"@method": "GET",
"with": true,
"from": "Sys_user_role",
"Sys_user_role": {
"@column": "role_id",
"user_id": "4732209c-5785-4827-b532-5092f154fd94"
}
},
"Sys_role": {
"id{}@": "sql"
},
"@Explain": true
}

另外, 我把一个json支持 不同操作,json格式调整了一下, 按照 上次你说的方式 更合理
image

image

赞,可以先提 PR,不用一开始就完美。 done is better than perfect.
敏捷开发,小步快跑。只要每次提交都整体比之前更好就行了,通过不断迭代来趋近完美。
而且据我观察 HEAD/HEADS 这两个本来用户就普遍用得很少,可以暂时先不管。

@TommyLemon
单条、批量 put、post多条、delete ,"@Explain": true 无法返回执行sql语句
image
一个json 包含多条语句 , 能正常返回
image

等我空了看看啥原因

建议先提个 PR 把功能提交上去,后面再提 PR 修改 bug,一次提交量太大的话往往不好 code review,bug 风险比较高,也不好定位

建议先提个 PR 把功能提交上去,后面再提 PR 修改 bug,一次提交量太大的话往往不好 code review,bug 风险比较高,也不好定位

嗯, 我先记下来

批量插入 "@Explain": true支持, 数组解析为单条sql语句的时候, 将 全局"@Explain": true打入 单条sql语句, 返回结果的时候,再处理一下,应该就可以了
image

@TommyLemon
batch json (一个json包含增删改查), 应该独立一个 controller方法,新定义一个 method, 自动解析 每个对象/数组/@Sql等 不同的method,走不同的流程.
我测下来, 如果url method = delete , json里面包含增删改查, 数组插入并不会执行.
url put、post能走完整流程

如果一个json支持 不同的method 操作
1、如果配置"@Explain" 能够看到一个事物中的所有执行sql语句
2、前置函数
前置函数能够将json语句, 像数组一样,解析成每一条语句 加入到 事物中

@TommyLemon batch json (一个json包含增删改查), 应该独立一个 controller方法,新定义一个 method, 自动解析 每个对象/数组/@Sql等 不同的method,走不同的流程. 我测下来, 如果url method = delete , json里面包含增删改查, 数组插入并不会执行. url put、post能走完整流程

对,这样更好,enum RequestMethod.java 新增 CRUD 这个枚举值,对应 URL 为 /crud,对于前端没传参 transaction: true 时自动放入 transaction: true。

如果一个json支持 不同的method 操作 1、如果配置"@Explain" 能够看到一个事物中的所有执行sql语句 2、前置函数 前置函数能够将json语句, 像数组一样,解析成每一条语句 加入到 事物中

1、这个目前就是的,在最外层全局传参 @explain: true 就返回所有的 SQL
https://github.com/Tencent/APIJSON/blob/master/Document.md#3.2
image

2、这个看起来不太好做,可以先提交 PR 后慢慢来

@TommyLemon
我现在在做PR, fox了最新的代码, demo示例项目的Function表returntype字段 应该改为 returnType,程序判断是 returnType
image

image
我看apijson 会支持function执行 javascript. 我们现在低代码平台 服务编排,一些简单的逻辑 javascrpt是通过node来动态执行.部署的时候打成静态代码

@TommyLemon 我现在在做PR, fox了最新的代码, demo示例项目的Function表returntype字段 应该改为 returnType,程序判断是 returnType image

image 我看apijson 会支持function执行 javascript. 我们现在低代码平台 服务编排,一些简单的逻辑 javascrpt是通过node来动态执行.部署的时候打成静态代码

是的,原来这个 returntype 没有用上,5.5.0(开发中)改成了 returnType,不仅用于 APIAuto 上展示给前端看返回类型,还会在启动时强制校验,保持和远程函数代码的方法实际返回类型一致。
已经支持执行 JavaScript 代码了,兼容 JDK 1.8-11 ,方便不会或不愿意写 Java 代码的同学,或者用于 Serverless 这种需要动态执行业务逻辑的需求,无需编译、重启服务等就能新增/修改业务逻辑。

@TommyLemon
也可以支持lua脚本

我整理的 优化建议: https://github.com/cloudAndMonkey/APIJSON#%E5%90%8E%E7%BB%AD%E4%BC%98%E5%8C%96%E5%BB%BA%E8%AE%AE

一个json能够执行不同的语句
javascript脚本已经支持
后续可以支持 通用rpc 、http、mq等远程调用函数
再搞一套 apijson执行解析 通用的redis、elasticSearch缓存模型
哈哈😄

@TommyLemon 也可以支持lua脚本

只要是 ScriptEngine 能支持的,也都考虑支持,毕竟实现也简单,只需要把 Function 表中配置的 type 的值(目前是 tinyint,后续改为 varchar) js, lua 等传参就行了
new ScriptEngineManager().getEngineByName(type);

https://github.com/Tencent/APIJSON/blob/master/APIJSONORM/src/main/java/apijson/orm/AbstractFunctionParser.java#L308-L310

我整理的 优化建议: https://github.com/cloudAndMonkey/APIJSON#%E5%90%8E%E7%BB%AD%E4%BC%98%E5%8C%96%E5%BB%BA%E8%AE%AE

一个json能够执行不同的语句 javascript脚本已经支持 后续可以支持 通用rpc 、http、mq等远程调用函数 再搞一套 apijson执行解析 通用的redis、elasticSearch缓存模型 哈哈😄

考虑集成 Redis 缓存到 apijson-framework。

rpc, http, mq 等远程函数用也考虑支持,不过可能是通过新增类似 apijson-column, apijson-router 等插件形式,或者集成到 apijson-framework。

目前已经支持 Elasticsearch-SQL 的协议及驱动,之前因为 token 问题导致查询报错 permission denied 无权限问题,可以用 5.4.0 试试。
https://github.com/APIJSON/APIJSON-Demo/tree/master/APIJSON-Java-Server/APIJSONDemo-Elasticsearch

@TommyLemon
我看到支持 elasticSearch 数据源, 个人觉得, 只是支持elasticSearch数据源, 太单一了
应用场景:
1、支持 多数据源、动态数据源(目前已经有)
mysql、redis、elasticSearch等
2、定义表结构字段 和 其他数据源,比如 elasticSearch document 关联关系
3、定义不同操作PUT、DELETE、GET、POST 数据库操作 以及 和 其他数据源的绑定、转换关联关系
4、json定义服务编排

  1. 插入数据库
  2. 按照规则、流程、对照关系, 操作其他数据源
  3. 插入数据库后, 需要对数据进行清洗, 逻辑处理, 可以通过javascript、function、lua等来实现

可以通过 @database, @Datasource 来指定数据源,同一个请求 JSON 中可以同时用多个不一样的数据源。

除了 SQL JOIN 不支持跨数据源,其它的操作都可以,例如 APP JOIN 和非 JOIN 的引用赋值

可以通过 @database, @Datasource 来指定数据源,同一个请求 JSON 中可以同时用多个不一样的数据源。

除了 SQL JOIN 不支持跨数据源,其它的操作都可以,例如 APP JOIN 和非 JOIN 的引用赋值
嗯嗯, 我要把json完善一下,把上面的功能做出来,哈哈

@cloudAndMonkey 发现个 bug,buildTag 把 Comment:[] 改成了 Comment[],导致查不到 Request 中 tag=Comment:[] 的记录
image
image

image

https://github.com/Tencent/APIJSON/blob/master/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java#L2201-L2218
image

版本5.2.0 1、业务表-插入不同表1:1、1:n、n:n 2、业务表-修改不同表1:1、1:n、n:n 3、业务表-批量删除不同表 实现流程: 1、继承APIJSONParser 2、重载 parseCorrectRequest方法 User__User 通过__分割, tag 和 structure的类名 新增, tag和 structure的类名一样, 更多示例请参见postman image image image 该方法,是参数校验入口 image 特定tag,则走分支流程 image image 修改引用关系 image postman测试示例: 业务表-插入不同表1:1-源码实现

{
    "User__User":{
        "username":"test2",
        "password": "123456",
		"state": 1
    },
    "User_address__User_address": 
	{
	"user_id@": "User/id",
	"addr": "ddd",
	"count": 1
	},
    "tag": "Batch_Tag_UserWithUser_addressList"
}

业务表-插入不同表1:n-源码实现

{
    "User__User":{
        "username":"test1",
        "password": "123456",
		"state": 1
    },
    "User_address[]__User_address[]": [
    	{
    	"user_id@": "User/id",
    	"addr": "ddd",
    	"count": 1
    	},
    	{
    	"user_id@": "User/id",
    	"addr": "ddd1",
    	"count": 2
    	}
    ],
    "tag": "Batch_Tag_UserWithUser_addressList"
}

业务表-插入不同表n:n-源码实现

{
    "User[]__User[]":[
    	{
        "username":"test3",
        "password": "123456",
		"state": 1
    	},
    	{
        "username":"test4",
        "password": "123456",
		"state": 1
    	}
    ],
    "User_address[]__User_address[]": [
    	{
    	"user_id": "94593122-403a-4eb2-a6f0-182ed3da7764",
    	"addr": "ddd",
    	"count": 1
    	},
    	{
    	"user_id": "94593122-403a-4eb2-a6f0-182ed3da7764",
    	"addr": "ddd1",
    	"count": 2
    	}
    ],
    "tag": "Batch_Tag_UserWithUser_addressList"
}

业务表-批量修改不同表1:n-源码实现

{
    "User__User":{
    	"id": "94593122-403a-4eb2-a6f0-182ed3da7764",
        "username":"test1-1",
        "password": "111111",
		"state": 1
    },
    "User_address[]__User_address[]": [
    	{
    	"id": "e8bb9e79-9bbe-49d2-9542-77792368bece",
    	"user_id@": "User/id",
    	"addr": "addr-01",
    	"count": 1
    	},
    	{
    	"id": "4dfee57f-6953-4371-865f-22b6e1957fee",
    	"user_id@": "User/id",
    	"addr": "addr-11",
    	"count": 1
    	}
    ],
    "tag": "Batch_Tag_UserWithUser_addressList"
}

业务表-批量修改不同表n:n-源码实现

{
    "User[]__User[]":[
    	{
    	"id": "f60e829a-1181-4331-ac1e-f5faf64e3a8c",
        "username":"test-3",
        "password": "123456-1",
		"state": 1
    	},
    	{
    	"id": "ca86a2e0-d504-4772-b06a-1a8c9e2b12c9",
        "username":"test-4",
        "password": "123456-1",
		"state": 1
    	}
    ],
    "User_address[]__User_address[]": [
    	{
    	"id": "faf8a605-66a3-4ce1-b774-c499b86a4984",
    	"user_id": "94593122-403a-4eb2-a6f0-182ed3da7764",
    	"addr": "ddd-1",
    	"count": 1
    	},
    	{
    	"id": "ac88ce16-6cdf-41a3-b382-c78452c5a850",
    	"user_id": "94593122-403a-4eb2-a6f0-182ed3da7764",
    	"addr": "ddd-2",
    	"count": 2
    	}
    ],
    "tag": "Batch_Tag_UserWithUser_addressList"
}

业务表-批量删除不同表-源码实现

{
    "User[]__User":{
    	"id{}": ["8e44c04a-6e90-4dfe-b021-3436453c55dd", "94593122-403a-4eb2-a6f0-182ed3da7764","ca86a2e0-d504-4772-b06a-1a8c9e2b12c9"]
    },
    "User_address[]__User_address": {
    	"id{}": ["1ed2dda1-5800-4b69-b128-7771dd79046f", "e8bb9e79-9bbe-49d2-9542-77792368bece","4dfee57f-6953-4371-865f-22b6e1957fee","faf8a605-66a3-4ce1-b774-c499b86a4984"]
    },
    "tag": "Batch_Tag_UserWithUser_addressList"
}

后续我再研究一下 1、支持不同的操作类型,比如 GET、POST、DELETE, 在一个json里面, 才能保证事物 2、function函数 执行语句, 加入事物 框架能支持数组, 把数组拆解为一条一条语句执行, 只要把相关引用 传递进 function应该能搞定,空了研究一下,哈哈

在加了 "@post": "Comment[],Comment:[]" 等后,看起来已经没有必要用 buildTag(下划线分割)这个方法了。

另外 Table:[] 这个是有必要的,因为 PUT 可以同时支持统一设置 Table[] 和单个设置 Table:[]
https://github.com/Tencent/APIJSON/blob/master/Document.md#3.1
image

批量新增或批量单独设置修改:新增配置允许部分子项失败
68bfce0

image

image

image

image

image

image

image

@cloudAndMonkey 发现个 bug,buildTag 把 Comment:[] 改成了 Comment[],导致查不到 Request 中 tag=Comment:[] 的记录 image image

image

https://github.com/Tencent/APIJSON/blob/master/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java#L2201-L2218 image

@cloudAndMonkey 改了这行可以解决,但可能对你加的新功能有影响,所以这里没有提交 Commit,你看下要怎么改哈
AbstractParser.buildTag

String _tag = tag; // buildTag(request, key);

https://github.com/Tencent/APIJSON/blob/master/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java#L2168
image

@cloudAndMonkey 发现个 bug,buildTag 把 Comment:[] 改成了 Comment[],导致查不到 Request 中 tag=Comment:[] 的记录 image image
image
https://github.com/Tencent/APIJSON/blob/master/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java#L2201-L2218 image

@cloudAndMonkey 改了这行可以解决,但可能对你加的新功能有影响,所以这里没有提交 Commit,你看下要怎么改哈 AbstractParser.buildTag

String _tag = tag; // buildTag(request, key);

https://github.com/Tencent/APIJSON/blob/master/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java#L2168 image

我看看

@TommyLemon
这里有个问题, 比如 Comment, 会同时支持 Comment[], Comment:[] ?
crud没有配置对象tag, 自动解析.
需要统一处理规则

@TommyLemon
tag就没法自动解析匹配了
crud ,对象里面配置吗?

"@post": {
		"User:aa": {
			 "@datasource": "db2"
		},
		"User_address[]": {
			 "@datasource": "db2"
		}
	}

以前也考虑过,但后面新增了简单接口形式:

/{method}/{tag}
{
  // content
}

每个请求 tag 也只有一个,就没必要了。

然而,你最近加的这个 /crud 全能增删改查接口,因为传参的 tag 太多了,还真有必要,而且实现也不难,
直接把 "@post": "User,User_address[]" 里的 key 作为默认的 tag,
如果是

"@post": {
	"User": { // 作为默认 tag
		"@datasource": "db2"
	},
	"User_address[]": {
                 "tag": "User_address:[]", // 有自定义 tag,不用默认的 User_address[]
		"@datasource": "db2"
	}
}

也是把 key 作为默认 tag,在内部传 tag 键值对才不用默认的

@TommyLemon
改好了,我提交一下
crud也支持Common:[] 新增,修改

感谢,已合并~

请问现在哪个版本支持 这种写法呢,目前下载的APIJSON5.4.jar好像没有呢

请问现在哪个版本支持 这种写法呢,目前下载的APIJSON5.4.jar好像没有呢

apijson6.0支持

请问现在哪个版本支持 这种写法呢,目前下载的APIJSON5.4.jar好像没有呢

apijson6.0支持

好的,谢谢

Alleyq commented

版本5.2.0 1、业务表-插入不同表1:1、1:n、n:n 2、业务表-修改不同表1:1、1:n、n:n 3、业务表-批量删除不同表 实现流程: 1、继承APIJSONParser 2、重载 parseCorrectRequest方法 User__User 通过__分割, tag 和 structure的类名 新增, tag和 structure的类名一样, 更多示例请参见postman image image image 该方法,是参数校验入口 image 特定tag,则走分支流程 image image 修改引用关系 image postman测试示例: 业务表-插入不同表1:1-源码实现

{
    "User__User":{
        "username":"test2",
        "password": "123456",
		"state": 1
    },
    "User_address__User_address": 
	{
	"user_id@": "User/id",
	"addr": "ddd",
	"count": 1
	},
    "tag": "Batch_Tag_UserWithUser_addressList"
}

业务表-插入不同表1:n-源码实现

{
    "User__User":{
        "username":"test1",
        "password": "123456",
		"state": 1
    },
    "User_address[]__User_address[]": [
    	{
    	"user_id@": "User/id",
    	"addr": "ddd",
    	"count": 1
    	},
    	{
    	"user_id@": "User/id",
    	"addr": "ddd1",
    	"count": 2
    	}
    ],
    "tag": "Batch_Tag_UserWithUser_addressList"
}

业务表-插入不同表n:n-源码实现

{
    "User[]__User[]":[
    	{
        "username":"test3",
        "password": "123456",
		"state": 1
    	},
    	{
        "username":"test4",
        "password": "123456",
		"state": 1
    	}
    ],
    "User_address[]__User_address[]": [
    	{
    	"user_id": "94593122-403a-4eb2-a6f0-182ed3da7764",
    	"addr": "ddd",
    	"count": 1
    	},
    	{
    	"user_id": "94593122-403a-4eb2-a6f0-182ed3da7764",
    	"addr": "ddd1",
    	"count": 2
    	}
    ],
    "tag": "Batch_Tag_UserWithUser_addressList"
}

业务表-批量修改不同表1:n-源码实现

{
    "User__User":{
    	"id": "94593122-403a-4eb2-a6f0-182ed3da7764",
        "username":"test1-1",
        "password": "111111",
		"state": 1
    },
    "User_address[]__User_address[]": [
    	{
    	"id": "e8bb9e79-9bbe-49d2-9542-77792368bece",
    	"user_id@": "User/id",
    	"addr": "addr-01",
    	"count": 1
    	},
    	{
    	"id": "4dfee57f-6953-4371-865f-22b6e1957fee",
    	"user_id@": "User/id",
    	"addr": "addr-11",
    	"count": 1
    	}
    ],
    "tag": "Batch_Tag_UserWithUser_addressList"
}

业务表-批量修改不同表n:n-源码实现

{
    "User[]__User[]":[
    	{
    	"id": "f60e829a-1181-4331-ac1e-f5faf64e3a8c",
        "username":"test-3",
        "password": "123456-1",
		"state": 1
    	},
    	{
    	"id": "ca86a2e0-d504-4772-b06a-1a8c9e2b12c9",
        "username":"test-4",
        "password": "123456-1",
		"state": 1
    	}
    ],
    "User_address[]__User_address[]": [
    	{
    	"id": "faf8a605-66a3-4ce1-b774-c499b86a4984",
    	"user_id": "94593122-403a-4eb2-a6f0-182ed3da7764",
    	"addr": "ddd-1",
    	"count": 1
    	},
    	{
    	"id": "ac88ce16-6cdf-41a3-b382-c78452c5a850",
    	"user_id": "94593122-403a-4eb2-a6f0-182ed3da7764",
    	"addr": "ddd-2",
    	"count": 2
    	}
    ],
    "tag": "Batch_Tag_UserWithUser_addressList"
}

业务表-批量删除不同表-源码实现

{
    "User[]__User":{
    	"id{}": ["8e44c04a-6e90-4dfe-b021-3436453c55dd", "94593122-403a-4eb2-a6f0-182ed3da7764","ca86a2e0-d504-4772-b06a-1a8c9e2b12c9"]
    },
    "User_address[]__User_address": {
    	"id{}": ["1ed2dda1-5800-4b69-b128-7771dd79046f", "e8bb9e79-9bbe-49d2-9542-77792368bece","4dfee57f-6953-4371-865f-22b6e1957fee","faf8a605-66a3-4ce1-b774-c499b86a4984"]
    },
    "tag": "Batch_Tag_UserWithUser_addressList"
}

后续我再研究一下 1、支持不同的操作类型,比如 GET、POST、DELETE, 在一个json里面, 才能保证事物 2、function函数 执行语句, 加入事物 框架能支持数组, 把数组拆解为一条一条语句执行, 只要把相关引用 传递进 function应该能搞定,空了研究一下,哈哈

请问 针对于 6.0.0的版本有调整吗?

@Alleyq 没有, 直接用

Alleyq commented

@Alleyq 没有, 直接用

有没有上传修改后的代码, 我看了你的项目库 没有看到有修改的代码 谢谢

Alleyq commented

@Alleyq 没有, 直接用

image
这几个方法是你本地实现的吧,有没有源码贴出来看下

@Alleyq 没有, 直接用

image 这几个方法是你本地实现的吧,有没有源码贴出来看下

全能crud method , APIJSON6.0 已经支持这些功能, 直接使用

比如如下格式, 你可以配置不同数据源, 相同数据源 非public method 支持事物

{
	"@datasource": "master",
	"@post": {
		"Access": {
			 "tag": "Access"
		},
		"Request[]": {
			 "tag": "Request[]"
		}
	},
    "Access": {
        "name": "Iinterface_list",
         "get": "[\"OWNER\", \"ADMIN\",\"LOGIN\"]",
                "head": "[\"OWNER\", \"ADMIN\",\"LOGIN\"]",
                "gets": "[\"OWNER\", \"ADMIN\",\"LOGIN\"]",
                "heads": "[\"OWNER\", \"ADMIN\",\"LOGIN\"]",
                "post": "[\"OWNER\", \"ADMIN\",\"LOGIN\"]",
                "put": "[\"OWNER\", \"ADMIN\",\"LOGIN\"]",
                "delete": "[\"OWNER\", \"ADMIN\",\"LOGIN\"]",
        "detail": "接口表"
    },
     "Request[]": [
        {
          "method": "POST",
          "tag": "Iinterface_list",
          "structure": "{\"MUST\": \"name,url,method,appId\", \"UPDATE\": {\"@role\": \"OWNER\"}, \"REFUSE\": \"id\"}",
          "detail": "新增"
        },
        {
          "method": "POST",
          "tag": "Iinterface_list[]",
          "structure": "{\"Iinterface_list[]\": [{\"MUST\": \"name,url,method,appId\", \"REFUSE\": \"id\"}], \"UPDATE\": {\"@role\": \"OWNER,ADMIN\"}}",
          "detail": "批量新增"
        },
        {
          "method": "PUT",
          "tag": "Iinterface_list",
          "structure": "{\"Iinterface_list\":{ \"MUST\":\"id\",\"REFUSE\": \"userId\", \"UPDATE\": {\"@role\": \"OWNER,ADMIN\"}} }",
          "detail": "修改"
        },
        {
          "method": "DELETE",
          "tag": "Iinterface_list",
          "structure": "{\"Iinterface_list\":{ \"MUST\":\"id\",\"REFUSE\": \"!\", \"INSERT\": {\"@role\": \"OWNER,ADMIN\"}} }",
          "detail": "批量删除"
        }
      ],
    "@explain": true
}
Alleyq commented

@Alleyq 没有, 直接用

image 这几个方法是你本地实现的吧,有没有源码贴出来看下

全能crud method , APIJSON6.0 已经支持这些功能, 直接使用

比如如下格式, 你可以配置不同数据源, 相同数据源 非public method 支持事物

{
   "@post": "User:aa,User_address[]",
   "User:aa":{
        "username":"test1",
        "password": "123456",
	"state": 1
    },
    "User_address[]": [
    	{
    	"user_id@": "User:aa/id",
    	"addr": "ddd",
    	"count": 1
    	},
    	{
    	"user_id@": "User:aa/id",
    	"addr": "ddd1",
    	"count": 2
    	}
    ],
    "@delete": "User:delUser,User_address:delUserAddress",
    "User:delUser":{
    	"id{}": ["1d863e0f-36ed-4817-98ef-690ea0769cd3"]
    },
    "User_address:delUserAddress": {
    	"id{}": ["75ea25d4-489d-4910-a5c8-8f1d24700887", "8106046c-5b5e-492f-8358-2d52fe47d936"]
    },
    "format": true,
    "@explain": true
}

您好 我的请求示例:
请求地址:
http://localhost:9898/crud
请求参数:
{
"@post": "User:aa",
"User:aa":{
"username":"test1",
"_password": "123456",
},
"format": true,
"@Explain": true
}

请求结果为什么是查询 ,我写的是post请求类型,为什么查询结果是 select?

{
"aa": {
"explain": {
"sql": "SELECT * FROM db_apijson.sys_user WHERE ( (username = 'test1') AND (_password = '123456') ) LIMIT 1",
"list": [
{
"id": 1,
"select_type": "SIMPLE",
"table": "sys_user",
"type": "ALL",
"rows": 2,
"filtered": 50.0,
"Extra": "Using where"
}
]
}
},
"format": true,
"explain": true,
"ok": true,
"code": 200,
"msg": "success",
"debug:info|help": " \n提 bug 请发请求和响应的【完整截屏】,没图的自行解决! \n开发者有限的时间和精力主要放在【维护项目源码和文档】上! \n【描述不详细】 或 【文档/常见问题 已有答案】 的问题可能会被忽略!! \n【态度 不文明/不友善】的可能会被踢出群,问题也可能不予解答!!! \n\n 环境信息 \n系统: Windows 10 10.0 \n数据库: DEFAULT_DATABASE = MYSQL \nJDK: 1.8.0_321 amd64 \nAPIJSON: 6.0.0 \n \n【常见问题】:#36 \n【通用文档】:https://github.com/Tencent/APIJSON/blob/master/Document.md \n【视频教程】:https://search.bilibili.com/all?keyword=APIJSON",
"sql:generate|cache|execute|maxExecute": "1|0|1|200",
"depth:count|max": "1|5",
"time:start|duration|end|parse|sql": "1677565710108|572|1677565710680|116|456"
}

@Alleyq 没有, 直接用

image 这几个方法是你本地实现的吧,有没有源码贴出来看下

全能crud method , APIJSON6.0 已经支持这些功能, 直接使用
比如如下格式, 你可以配置不同数据源, 相同数据源 非public method 支持事物

{
   "@post": "User:aa,User_address[]",
   "User:aa":{
        "username":"test1",
        "password": "123456",
	"state": 1
    },
    "User_address[]": [
    	{
    	"user_id@": "User:aa/id",
    	"addr": "ddd",
    	"count": 1
    	},
    	{
    	"user_id@": "User:aa/id",
    	"addr": "ddd1",
    	"count": 2
    	}
    ],
    "@delete": "User:delUser,User_address:delUserAddress",
    "User:delUser":{
    	"id{}": ["1d863e0f-36ed-4817-98ef-690ea0769cd3"]
    },
    "User_address:delUserAddress": {
    	"id{}": ["75ea25d4-489d-4910-a5c8-8f1d24700887", "8106046c-5b5e-492f-8358-2d52fe47d936"]
    },
    "format": true,
    "@explain": true
}

您好 我的请求示例: 请求地址: http://localhost:9898/crud 请求参数: { "@post": "User:aa", "User:aa":{ "username":"test1", "_password": "123456", }, "format": true, "@Explain": true }

请求结果为什么是查询 ,我写的是post请求类型,为什么查询结果是 select?

{ "aa": { "explain": { "sql": "SELECT * FROM db_apijson.sys_user WHERE ( (username = 'test1') AND (_password = '123456') ) LIMIT 1", "list": [ { "id": 1, "select_type": "SIMPLE", "table": "sys_user", "type": "ALL", "rows": 2, "filtered": 50.0, "Extra": "Using where" } ] } }, "format": true, "explain": true, "ok": true, "code": 200, "msg": "success", "debug:info|help": " \n提 bug 请发请求和响应的【完整截屏】,没图的自行解决! \n开发者有限的时间和精力主要放在【维护项目源码和文档】上! \n【描述不详细】 或 【文档/常见问题 已有答案】 的问题可能会被忽略!! \n【态度 不文明/不友善】的可能会被踢出群,问题也可能不予解答!!! \n\n 环境信息 \n系统: Windows 10 10.0 \n数据库: DEFAULT_DATABASE = MYSQL \nJDK: 1.8.0_321 amd64 \nAPIJSON: 6.0.0 \n \n【常见问题】:#36 \n【通用文档】:https://github.com/Tencent/APIJSON/blob/master/Document.md \n【视频教程】:https://search.bilibili.com/all?keyword=APIJSON", "sql:generate|cache|execute|maxExecute": "1|0|1|200", "depth:count|max": "1|5", "time:start|duration|end|parse|sql": "1677565710108|572|1677565710680|116|456" }

@Alleyq
示例发错了, 你看我重新发的

Alleyq commented

@Alleyq 没有, 直接用

image 这几个方法是你本地实现的吧,有没有源码贴出来看下

全能crud method , APIJSON6.0 已经支持这些功能, 直接使用
比如如下格式, 你可以配置不同数据源, 相同数据源 非public method 支持事物

{
   "@post": "User:aa,User_address[]",
   "User:aa":{
        "username":"test1",
        "password": "123456",
	"state": 1
    },
    "User_address[]": [
    	{
    	"user_id@": "User:aa/id",
    	"addr": "ddd",
    	"count": 1
    	},
    	{
    	"user_id@": "User:aa/id",
    	"addr": "ddd1",
    	"count": 2
    	}
    ],
    "@delete": "User:delUser,User_address:delUserAddress",
    "User:delUser":{
    	"id{}": ["1d863e0f-36ed-4817-98ef-690ea0769cd3"]
    },
    "User_address:delUserAddress": {
    	"id{}": ["75ea25d4-489d-4910-a5c8-8f1d24700887", "8106046c-5b5e-492f-8358-2d52fe47d936"]
    },
    "format": true,
    "@explain": true
}

您好 我的请求示例: 请求地址: http://localhost:9898/crud 请求参数: { "@post": "User:aa", "User:aa":{ "username":"test1", "_password": "123456", }, "format": true, "@Explain": true }
请求结果为什么是查询 ,我写的是post请求类型,为什么查询结果是 select?
{ "aa": { "explain": { "sql": "SELECT * FROM db_apijson.sys_user WHERE ( (username = 'test1') AND (_password = '123456') ) LIMIT 1", "list": [ { "id": 1, "select_type": "SIMPLE", "table": "sys_user", "type": "ALL", "rows": 2, "filtered": 50.0, "Extra": "Using where" } ] } }, "format": true, "explain": true, "ok": true, "code": 200, "msg": "success", "debug:info|help": " \n提 bug 请发请求和响应的【完整截屏】,没图的自行解决! \n开发者有限的时间和精力主要放在【维护项目源码和文档】上! \n【描述不详细】 或 【文档/常见问题 已有答案】 的问题可能会被忽略!! \n【态度 不文明/不友善】的可能会被踢出群,问题也可能不予解答!!! \n\n 环境信息 \n系统: Windows 10 10.0 \n数据库: DEFAULT_DATABASE = MYSQL \nJDK: 1.8.0_321 amd64 \nAPIJSON: 6.0.0 \n \n【常见问题】:#36 \n【通用文档】:https://github.com/Tencent/APIJSON/blob/master/Document.md \n【视频教程】:https://search.bilibili.com/all?keyword=APIJSON", "sql:generate|cache|execute|maxExecute": "1|0|1|200", "depth:count|max": "1|5", "time:start|duration|end|parse|sql": "1677565710108|572|1677565710680|116|456" }

@Alleyq 示例发错了, 你看我重新发的

我想问下请求地址是用 /crud 这个方法吗 还是用别的什么方法 ,文档里面没有详细说明这一块 谢谢老哥

/crud 这个方法 autoapi 使用示例 和 官网使用示例 要等我空了再加

Alleyq commented

/crud 这个方法 autoapi 使用示例 和 官网使用示例 要等我空了再加
我看了源码 这个@post 只接收 JSONObject
源码:
image

我最后改的传值:

{ "@put": { "UserPrivacy": {} }, "UserPrivacy": { "id": "1", "roles": "li222si" }, "format": true, "@explain": true }
执行结果:
{ "userPrivacy": { "sql": "UPDATEdb_apijson.user_privacySETroles = 'li222si' WHERE ( (id= '1') ) LIMIT 1", "ok": true, "code": 200, "msg": "success", "count": 1, "id": "1" }, "format": true, "explain": true, "ok": true, "code": 200, "msg": "success", }

是不是要重写下源码里面这段代码还是怎么滴,我很郁闷 大哥帮忙解惑

你的修改能正常, 改一个post示例测一下呀
重新编辑了示例, 增删改查,跨数据源都可以

{
	"@datasource": "master",
	"@post": {
		"Access": {
			 "tag": "Access"
		},
		"Request[]": {
			 "tag": "Request[]"
		}
	},
    "Access": {
        "name": "Iinterface_list",
         "get": "[\"OWNER\", \"ADMIN\",\"LOGIN\"]",
                "head": "[\"OWNER\", \"ADMIN\",\"LOGIN\"]",
                "gets": "[\"OWNER\", \"ADMIN\",\"LOGIN\"]",
                "heads": "[\"OWNER\", \"ADMIN\",\"LOGIN\"]",
                "post": "[\"OWNER\", \"ADMIN\",\"LOGIN\"]",
                "put": "[\"OWNER\", \"ADMIN\",\"LOGIN\"]",
                "delete": "[\"OWNER\", \"ADMIN\",\"LOGIN\"]",
        "detail": "接口表"
    },
     "Request[]": [
        {
          "method": "POST",
          "tag": "Iinterface_list",
          "structure": "{\"MUST\": \"name,url,method,appId\", \"UPDATE\": {\"@role\": \"OWNER\"}, \"REFUSE\": \"id\"}",
          "detail": "新增"
        },
        {
          "method": "POST",
          "tag": "Iinterface_list[]",
          "structure": "{\"Iinterface_list[]\": [{\"MUST\": \"name,url,method,appId\", \"REFUSE\": \"id\"}], \"UPDATE\": {\"@role\": \"OWNER,ADMIN\"}}",
          "detail": "批量新增"
        },
        {
          "method": "PUT",
          "tag": "Iinterface_list",
          "structure": "{\"Iinterface_list\":{ \"MUST\":\"id\",\"REFUSE\": \"userId\", \"UPDATE\": {\"@role\": \"OWNER,ADMIN\"}} }",
          "detail": "修改"
        },
        {
          "method": "DELETE",
          "tag": "Iinterface_list",
          "structure": "{\"Iinterface_list\":{ \"MUST\":\"id\",\"REFUSE\": \"!\", \"INSERT\": {\"@role\": \"OWNER,ADMIN\"}} }",
          "detail": "批量删除"
        }
      ],
    "@explain": true
}
Alleyq commented

你的修改能正常, 改一个post示例测一下呀 重新编辑了示例, 增删改查,跨数据源都可以

{
	"@datasource": "master",
	"@post": {
		"Access": {
			 "tag": "Access"
		},
		"Request[]": {
			 "tag": "Request[]"
		}
	},
    "Access": {
        "name": "Iinterface_list",
         "get": "[\"OWNER\", \"ADMIN\",\"LOGIN\"]",
                "head": "[\"OWNER\", \"ADMIN\",\"LOGIN\"]",
                "gets": "[\"OWNER\", \"ADMIN\",\"LOGIN\"]",
                "heads": "[\"OWNER\", \"ADMIN\",\"LOGIN\"]",
                "post": "[\"OWNER\", \"ADMIN\",\"LOGIN\"]",
                "put": "[\"OWNER\", \"ADMIN\",\"LOGIN\"]",
                "delete": "[\"OWNER\", \"ADMIN\",\"LOGIN\"]",
        "detail": "接口表"
    },
     "Request[]": [
        {
          "method": "POST",
          "tag": "Iinterface_list",
          "structure": "{\"MUST\": \"name,url,method,appId\", \"UPDATE\": {\"@role\": \"OWNER\"}, \"REFUSE\": \"id\"}",
          "detail": "新增"
        },
        {
          "method": "POST",
          "tag": "Iinterface_list[]",
          "structure": "{\"Iinterface_list[]\": [{\"MUST\": \"name,url,method,appId\", \"REFUSE\": \"id\"}], \"UPDATE\": {\"@role\": \"OWNER,ADMIN\"}}",
          "detail": "批量新增"
        },
        {
          "method": "PUT",
          "tag": "Iinterface_list",
          "structure": "{\"Iinterface_list\":{ \"MUST\":\"id\",\"REFUSE\": \"userId\", \"UPDATE\": {\"@role\": \"OWNER,ADMIN\"}} }",
          "detail": "修改"
        },
        {
          "method": "DELETE",
          "tag": "Iinterface_list",
          "structure": "{\"Iinterface_list\":{ \"MUST\":\"id\",\"REFUSE\": \"!\", \"INSERT\": {\"@role\": \"OWNER,ADMIN\"}} }",
          "detail": "批量删除"
        }
      ],
    "@explain": true
}

看到啦 , 感谢感谢 ~

Alleyq commented

你的修改能正常, 改一个post示例测一下呀 重新编辑了示例, 增删改查,跨数据源都可以

{
	"@datasource": "master",
	"@post": {
		"Access": {
			 "tag": "Access"
		},
		"Request[]": {
			 "tag": "Request[]"
		}
	},
    "Access": {
        "name": "Iinterface_list",
         "get": "[\"OWNER\", \"ADMIN\",\"LOGIN\"]",
                "head": "[\"OWNER\", \"ADMIN\",\"LOGIN\"]",
                "gets": "[\"OWNER\", \"ADMIN\",\"LOGIN\"]",
                "heads": "[\"OWNER\", \"ADMIN\",\"LOGIN\"]",
                "post": "[\"OWNER\", \"ADMIN\",\"LOGIN\"]",
                "put": "[\"OWNER\", \"ADMIN\",\"LOGIN\"]",
                "delete": "[\"OWNER\", \"ADMIN\",\"LOGIN\"]",
        "detail": "接口表"
    },
     "Request[]": [
        {
          "method": "POST",
          "tag": "Iinterface_list",
          "structure": "{\"MUST\": \"name,url,method,appId\", \"UPDATE\": {\"@role\": \"OWNER\"}, \"REFUSE\": \"id\"}",
          "detail": "新增"
        },
        {
          "method": "POST",
          "tag": "Iinterface_list[]",
          "structure": "{\"Iinterface_list[]\": [{\"MUST\": \"name,url,method,appId\", \"REFUSE\": \"id\"}], \"UPDATE\": {\"@role\": \"OWNER,ADMIN\"}}",
          "detail": "批量新增"
        },
        {
          "method": "PUT",
          "tag": "Iinterface_list",
          "structure": "{\"Iinterface_list\":{ \"MUST\":\"id\",\"REFUSE\": \"userId\", \"UPDATE\": {\"@role\": \"OWNER,ADMIN\"}} }",
          "detail": "修改"
        },
        {
          "method": "DELETE",
          "tag": "Iinterface_list",
          "structure": "{\"Iinterface_list\":{ \"MUST\":\"id\",\"REFUSE\": \"!\", \"INSERT\": {\"@role\": \"OWNER,ADMIN\"}} }",
          "detail": "批量删除"
        }
      ],
    "@explain": true
}

看到啦 , 感谢感谢 ~

老哥,如果同时新增两张表,第二个表的某个字段引用第一个表的新增主键,这个要怎么写呢?下面是我的代码
{ "@post": { "User": {}, "UserPrivacy": {} }, "User": { "nickName": "all2ey1", "phone": "18576496089", "sex": "2", "userName": "alley" }, "UserPrivacy": { "userId@":"User/id" } }
执行提示: "msg": "POST 请求必须在Table内设置要保存的 key:value !",

1、引用主表id, 配置 id 由应用生成,比如uuid
https://github.com/cloudAndMonkey/APIJSON-Demo/blob/master/APIJSON-Java-Server/APIJSONBoot/src/main/java/apijson/demo/DemoSQLConfig.java#L91-L95
2、引用方式如下:

"User:aa":{
        "username":"test-3",
        "password": "233223",
		"state": 1
    },
"User_address[]": [
    	{
    	"user_id@": "User:aa/id",
    	"addr": "ddd"
    	}
    ]

至于 数据库生成id 引用, 看看官网文档, 测一下

Alleyq commented

1、引用主表id, 配置 id 由应用生成,比如uuid https://github.com/cloudAndMonkey/APIJSON-Demo/blob/master/APIJSON-Java-Server/APIJSONBoot/src/main/java/apijson/demo/DemoSQLConfig.java#L91-L95 2、引用方式如下:

"User:aa":{
        "username":"test-3",
        "password": "233223",
		"state": 1
    },
"User_address[]": [
    	{
    	"user_id@": "User:aa/id",
    	"addr": "ddd"
    	}
    ]

至于 数据库生成id 引用, 看看官网文档, 测一下

老哥 批量新增这个条数限制,如果改源码的话会有性能的问题吗 ?

1、引用主表id, 配置 id 由应用生成,比如uuid https://github.com/cloudAndMonkey/APIJSON-Demo/blob/master/APIJSON-Java-Server/APIJSONBoot/src/main/java/apijson/demo/DemoSQLConfig.java#L91-L95 2、引用方式如下:

"User:aa":{
        "username":"test-3",
        "password": "233223",
		"state": 1
    },
"User_address[]": [
    	{
    	"user_id@": "User:aa/id",
    	"addr": "ddd"
    	}
    ]

至于 数据库生成id 引用, 看看官网文档, 测一下

老哥 批量新增这个条数限制,如果改源码的话会有性能的问题吗 ?

不用改源码,子类实现方法即可
https://github.com/Tencent/APIJSON/blob/master/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java#LL69-L110

版本6.0.0的APIJSON
您好:这种格式的请求现在不适配了吗
123123123
2222222
我看每个子json都是单独解析的
333331

版本6.0.0的APIJSON 您好:这种格式的请求现在不适配了吗 123123123 2222222 我看每个子json都是单独解析的 333331

@wahowaho
是个新引入的 bug
#512

这里不应该只 requestItem.put(_key, obj),丢了 "Request":{} 对象导致 objectVerify 抛异常,
应该把原始请求的所有键值对 put 进去,可以 requestItem.putAll(原来的 request 对象)。

可以改下源码试试,如果可以麻烦提 PR 贡献下代码哦,开源要大家一起参与贡献才会更美好~
https://github.com/Tencent/APIJSON/blob/master/CONTRIBUTING.md

image

版本6.0.0的APIJSON 您好:这种格式的请求现在不适配了吗 123123123 2222222 我看每个子json都是单独解析的 333331

@wahowaho 是个新引入的 bug #512

这里不应该只 requestItem.put(_key, obj),丢了 "Request":{} 对象导致 objectVerify 抛异常, 应该把原始请求的所有键值对 put 进去,可以 requestItem.putAll(原来的 request 对象)。

可以改下源码试试,如果可以麻烦提 PR 贡献下代码哦,开源要大家一起参与贡献才会更美好~ https://github.com/Tencent/APIJSON/blob/master/CONTRIBUTING.md

image

我来看看

为啥每个 JSONObject 进行解析, 一方面是为了解决别名

{
    "Access:a":{
        "id": "1"
    },
    "Request:b":{
        "id@": "/Access/id"
    },
    "tag": "Request"
}

为啥每个 JSONObject 进行解析, 一方面是为了解决别名

{
    "Access:a":{
        "id": "1"
    },
    "Request:b":{
        "id@": "/Access/id"
    },
    "tag": "Request"
}

@cloudAndMonkey
别名不用提前解析,同一层没有重复表名的话建议不用别名.
如果有别名,也可以直接在 Request 表 structure 字段里配置:

{
    "Access:a":{
        "MUST": "id"
    },
    "Request:b":{
        "UPDATE": {
            "id@": "/Access/id"
        }
    }
}

为啥每个 JSONObject 进行解析, 一方面是为了解决别名

{
    "Access:a":{
        "id": "1"
    },
    "Request:b":{
        "id@": "/Access/id"
    },
    "tag": "Request"
}

@cloudAndMonkey 别名不用提前解析,同一层没有重复表名的话建议不用别名. 如果有别名,也可以直接在 Request 表 structure 字段里配置:

{
    "Access:a":{
        "MUST": "id"
    },
    "Request:b":{
        "UPDATE": {
            "id@": "/Access/id"
        }
    }
}

那我测一下, crud 和其他方法都统一这么做

@cloudAndMonkey
刚刚 @wahowaho 提了个修复的 PR:
#545

@cloudAndMonkey 刚刚 @wahowaho 提了个修复的 PR: #545

嗯嗯, 看到了, 需要删除tag 、JSONObject 别名判断的代码 , 今天晚上我好好梳理一下

@TommyLemon
无别名
image

有别名
image

差不多改好了, 我拉通测一下,需要覆盖各种场景, 把 function 事物一起完善,再提交
比如: Comment:[] 支持别名等

INSERT INTO `apijson`.`Request` (`id`, `debug`, `version`, `method`, `tag`, `structure`, `detail`, `date`) VALUES (45, 0, 2, 'POST', 'Comment:[]', '{\"TYPE\": {\"Comment[]\": \"OBJECT[]\"}, \"INSERT\": {\"@role\": \"OWNER\"}, \"Comment[]\": []}', NULL, '2020-03-01 13:40:04');

最近有点忙, 不好意思😄

@TommyLemon
代码已经提交

image

把 \ 去掉了, 代码在报错

完善同一个请求内多种不同操作的关键词,新增支持

@post: "User", // 相当于 "User": { "tag": "User" }
@gets: { 
    "Privacy": "Privacy-phone" // 相当于 "Privacy": { "tag": "Privacy-phone" }
} 

等简化写法
eccf252

求助两位大佬,请问主键非id情况下需要单另外配置什么信息,目前主键为xxx_id,增删改均报错Unknown column 'id' in 'field list'

@15207126400

求助两位大佬,请问主键非id情况下需要单另外配置什么信息,目前主键为xxx_id,增删改均报错Unknown column 'id' in 'field list'

image