From ac141549222ff006273063fa2a5e6150062bcf0e Mon Sep 17 00:00:00 2001 From: TommyLemon <1184482681@qq.com> Date: Sat, 14 Mar 2026 13:07:56 +0800 Subject: [PATCH 01/33] doc: Document.md add Chinese entrance --- Document.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Document.md b/Document.md index 7574e569..d6929597 100644 --- a/Document.md +++ b/Document.md @@ -1,3 +1,5 @@ +## English | [中文](/blob/master/README-Chinese.md) + #### A better online document is available at https://apijsondocs.readthedocs.io ### Examples: From 35805a72dde88ce417e7793961619fb9f7b0ffd8 Mon Sep 17 00:00:00 2001 From: TommyLemon <1184482681@qq.com> Date: Sat, 14 Mar 2026 13:08:36 +0800 Subject: [PATCH 02/33] Update Document.md --- Document.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Document.md b/Document.md index d6929597..d3f18d4a 100644 --- a/Document.md +++ b/Document.md @@ -1,4 +1,4 @@ -## English | [中文](/blob/master/README-Chinese.md) +## English | [中文](https://github.com/Tencent/APIJSON/blob/master/Document-Chinese.md) #### A better online document is available at https://apijsondocs.readthedocs.io From b591dc7318659864b70d139754ea199e8fe6faa8 Mon Sep 17 00:00:00 2001 From: TommyLemon <1184482681@qq.com> Date: Sat, 14 Mar 2026 13:09:19 +0800 Subject: [PATCH 03/33] Update Document-Chinese.md --- Document-Chinese.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Document-Chinese.md b/Document-Chinese.md index 11db6fe8..65caa417 100644 --- a/Document-Chinese.md +++ b/Document-Chinese.md @@ -1,5 +1,4 @@ -[English](https://github.com/Tencent/APIJSON/blob/master/Document-English.md) -
+## 中文 | [English](https://github.com/Tencent/APIJSON/blob/master/Document-English.md) # APIJSON 通用文档 本文是通用文档,只和 APIJSON 协议有关,和 C#, Go, Java, JavaScript, PHP, Python, TypeScript 等开发语言无关。
From 7a53f3be99f019e7e296acc213f753428d3fe679 Mon Sep 17 00:00:00 2001 From: TommyLemon <1184482681@qq.com> Date: Sat, 14 Mar 2026 13:09:49 +0800 Subject: [PATCH 04/33] Update Document-Chinese.md --- Document-Chinese.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Document-Chinese.md b/Document-Chinese.md index 65caa417..ffe8e975 100644 --- a/Document-Chinese.md +++ b/Document-Chinese.md @@ -1,4 +1,4 @@ -## 中文 | [English](https://github.com/Tencent/APIJSON/blob/master/Document-English.md) +## 中文 | [English](https://github.com/Tencent/APIJSON/blob/master/Document.md) # APIJSON 通用文档 本文是通用文档,只和 APIJSON 协议有关,和 C#, Go, Java, JavaScript, PHP, Python, TypeScript 等开发语言无关。
From bd5151b60ab9b5194ea55607a10f5d09fe420d51 Mon Sep 17 00:00:00 2001 From: TommyLemon Date: Sun, 29 Mar 2026 16:15:04 +0800 Subject: [PATCH 05/33] =?UTF-8?q?=E7=BB=93=E6=9E=9C=E9=9B=86=E5=AE=B9?= =?UTF-8?q?=E9=87=8F=E9=A2=84=E4=BC=B0=EF=BC=9A=E6=9C=80=E4=BD=8E=E5=BC=80?= =?UTF-8?q?=E5=90=AF=E9=98=88=E5=80=BC=E9=BB=98=E8=AE=A4=E8=AE=BE=E7=BD=AE?= =?UTF-8?q?=E4=B8=BA=202^16=20-=201=20=3D=2065535=EF=BC=8CArrayList=20?= =?UTF-8?q?=E6=9C=80=E5=A4=9A=E6=89=A9=E5=AE=B9=205=20=E6=AC=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/apijson/orm/AbstractSQLExecutor.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractSQLExecutor.java b/APIJSONORM/src/main/java/apijson/orm/AbstractSQLExecutor.java index 8a2862eb..7870d3df 100755 --- a/APIJSONORM/src/main/java/apijson/orm/AbstractSQLExecutor.java +++ b/APIJSONORM/src/main/java/apijson/orm/AbstractSQLExecutor.java @@ -158,6 +158,8 @@ public ResultSet execute(@NotNull Statement statement, String sql) throws Except return rs; } + public static int MIN_OPTIMIZE_CAPACITY = 2^16 - 1; + /**执行SQL * @param config * @return @@ -330,7 +332,7 @@ public M execute(@NotNull SQLConfig config, boolean unknownType) throws } else { // 预估容量 capacity = config.getCount() <= 0 ? AbstractParser.MAX_QUERY_COUNT : config.getCount(); - if (capacity > 100) { + if (capacity > MIN_OPTIMIZE_CAPACITY) { // 有 WHERE 条件,条件越多过滤数据越多,暂时不考虑 @combine:"a | (b & !c)" 里面 | OR 和 ! NOT 条件,太复杂也不是很必要 Map> combine = config.getCombineMap(); @@ -354,14 +356,15 @@ public M execute(@NotNull SQLConfig config, boolean unknownType) throws Map having = config.getHaving(); int havingCount = having == null ? 0 : having.size(); - capacity /= Math.pow(1.5, Math.log10(capacity) + double cap = capacity / Math.pow(1.5, Math.log10(capacity) + andCondCount + ((orCondCount <= 0 ? 0 : 2.0d/orCondCount) // 1: 2.3, 2: 1.5, 3: 1.3, 4: 1.23, 5: 1.18 + (notCondCount/5.0d) // 1: 1.08, 2: 1.18, 3: 1.28, 4: 1.38, 1.50 + (groupCount <= 0 ? 0 : 10.0d/groupCount)) // 1: 57.7, 7.6, 3: 3.9, 4: 2.8, 5: 2.3 + havingCount ); - capacity += 1; // 避免正好比需要容量少一点点导致多一次扩容,大量数据 System.arrayCopy + cap = Math.max(MIN_OPTIMIZE_CAPACITY, Math.max(cap, capacity/Math.pow(1.5, 5))); // 1/(1.5^5) = 0.13 + capacity = (int) (cap + 1); // 避免正好比需要容量少一点点导致多一次扩容,大量数据 System.arrayCopy } } } From f63e2ad244bbcc8f8060c55d96274bad2f13fef6 Mon Sep 17 00:00:00 2001 From: TommyLemon Date: Sun, 29 Mar 2026 16:28:54 +0800 Subject: [PATCH 06/33] =?UTF-8?q?=E7=BB=93=E6=9E=9C=E9=9B=86=E5=AE=B9?= =?UTF-8?q?=E9=87=8F=E9=A2=84=E4=BC=B0=EF=BC=9A=E4=BC=98=E5=8C=96=20GROUP?= =?UTF-8?q?=20BY=20=E5=87=8F=E5=B0=91=E5=88=9D=E5=A7=8B=E5=AE=B9=E9=87=8F?= =?UTF-8?q?=E4=B8=8B=E9=99=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- APIJSONORM/src/main/java/apijson/orm/AbstractSQLExecutor.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractSQLExecutor.java b/APIJSONORM/src/main/java/apijson/orm/AbstractSQLExecutor.java index 7870d3df..bddfad26 100755 --- a/APIJSONORM/src/main/java/apijson/orm/AbstractSQLExecutor.java +++ b/APIJSONORM/src/main/java/apijson/orm/AbstractSQLExecutor.java @@ -360,10 +360,10 @@ public M execute(@NotNull SQLConfig config, boolean unknownType) throws + andCondCount + ((orCondCount <= 0 ? 0 : 2.0d/orCondCount) // 1: 2.3, 2: 1.5, 3: 1.3, 4: 1.23, 5: 1.18 + (notCondCount/5.0d) // 1: 1.08, 2: 1.18, 3: 1.28, 4: 1.38, 1.50 - + (groupCount <= 0 ? 0 : 10.0d/groupCount)) // 1: 57.7, 7.6, 3: 3.9, 4: 2.8, 5: 2.3 + + (groupCount <= 0 ? 0 : 10.0d/Math.min(5, groupCount))) // 1: 57.7, 7.6, 3: 3.9, 4: 2.8, 5: 2.3 + havingCount ); - cap = Math.max(MIN_OPTIMIZE_CAPACITY, Math.max(cap, capacity/Math.pow(1.5, 5))); // 1/(1.5^5) = 0.13 + cap = groupCount > 0 ? cap : Math.max(MIN_OPTIMIZE_CAPACITY, Math.max(cap, capacity/Math.pow(1.5, 5))); // 1/(1.5^5) = 0.13 capacity = (int) (cap + 1); // 避免正好比需要容量少一点点导致多一次扩容,大量数据 System.arrayCopy } } From 46c9f3be16e3ffcfbf75c71739438e9554549af3 Mon Sep 17 00:00:00 2001 From: TommyLemon Date: Sun, 29 Mar 2026 17:04:32 +0800 Subject: [PATCH 07/33] =?UTF-8?q?=E7=BB=93=E6=9E=9C=E9=9B=86=E5=AE=B9?= =?UTF-8?q?=E9=87=8F=E9=A2=84=E4=BC=B0=EF=BC=9ALIMIT=2010^9=20=3D=201=20?= =?UTF-8?q?=E4=BA=BF=20=E4=BB=A5=E5=86=85=E6=97=A0=E4=BB=BB=E4=BD=95?= =?UTF-8?q?=E6=9D=A1=E4=BB=B6=E6=97=B6=20=E6=9C=80=E5=A4=9A=E6=89=A9?= =?UTF-8?q?=E5=AE=B9=201=20=E6=AC=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- APIJSONORM/src/main/java/apijson/orm/AbstractSQLExecutor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractSQLExecutor.java b/APIJSONORM/src/main/java/apijson/orm/AbstractSQLExecutor.java index bddfad26..3107b905 100755 --- a/APIJSONORM/src/main/java/apijson/orm/AbstractSQLExecutor.java +++ b/APIJSONORM/src/main/java/apijson/orm/AbstractSQLExecutor.java @@ -356,7 +356,7 @@ public M execute(@NotNull SQLConfig config, boolean unknownType) throws Map having = config.getHaving(); int havingCount = having == null ? 0 : having.size(); - double cap = capacity / Math.pow(1.5, Math.log10(capacity) + double cap = capacity / Math.pow(1.5, Math.log10(capacity)/8 // LIMIT 10^9 = 1 亿 以内无任何条件时 最多扩容 1 次 + andCondCount + ((orCondCount <= 0 ? 0 : 2.0d/orCondCount) // 1: 2.3, 2: 1.5, 3: 1.3, 4: 1.23, 5: 1.18 + (notCondCount/5.0d) // 1: 1.08, 2: 1.18, 3: 1.28, 4: 1.38, 1.50 From 696656a530fff2c12ce50c393f50ff6997d723b0 Mon Sep 17 00:00:00 2001 From: TommyLemon Date: Sun, 29 Mar 2026 17:07:27 +0800 Subject: [PATCH 08/33] =?UTF-8?q?=E5=8D=87=E7=BA=A7=E7=89=88=E6=9C=AC?= =?UTF-8?q?=E4=B8=BA=208.1.5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- APIJSONORM/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/APIJSONORM/pom.xml b/APIJSONORM/pom.xml index 8b36d0da..4ce8f9af 100644 --- a/APIJSONORM/pom.xml +++ b/APIJSONORM/pom.xml @@ -5,7 +5,7 @@ com.github.Tencent APIJSON - 8.1.3 + 8.1.5 jar APIJSONORM From a303055f18124a6bd3143d38b8dbee747127ff3b Mon Sep 17 00:00:00 2001 From: TommyLemon <1184482681@qq.com> Date: Sun, 29 Mar 2026 19:05:49 +0800 Subject: [PATCH 09/33] =?UTF-8?q?=20=E6=9B=BF=E6=8D=A2=20apijson-rust=20?= =?UTF-8?q?=E9=93=BE=E6=8E=A5=EF=BC=9Ahttps://github.com/APIJSON/apijson-r?= =?UTF-8?q?ust?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 创作不易,右上角点亮 ⭐Star 来支持/收藏下吧,谢谢 ^_^ https://github.com/APIJSON/apijson-rust https://gitee.com/APIJSON/apijson-rust --- README-Chinese.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README-Chinese.md b/README-Chinese.md index efd1858f..ceb1ef25 100644 --- a/README-Chinese.md +++ b/README-Chinese.md @@ -699,7 +699,7 @@ Issue/问卷 一般解答顺序:贡献者 > 帮助他人的用户 > 提供任 [uliweb-apijson](https://github.com/zhangchunlin/uliweb-apijson) Python 版 APIJSON,支持 MySQL, PostgreSQL, SQL Server, Oracle, SQLite 等 -[apijson-rust](https://gitee.com/APIJSON/panda-base) APIJSON 的 Rust 版,一个优雅、高性能的 Rust 多数据源管理系统,支持 MySQL 和 PostgreSQL +[apijson-rust](https://github.com/APIJSON/apijson-rust) APIJSON 的 Rust 版,一个优雅、高性能的 Rust 多数据源管理系统,支持 MySQL 和 PostgreSQL [APIJSONParser](https://github.com/Zerounary/APIJSONParser) 第三方 APIJSON 解析器,将 JSON 动态解析成 SQL From d955657d1ffbb40b48be900d154d0c38e92c74f1 Mon Sep 17 00:00:00 2001 From: TommyLemon Date: Sat, 18 Apr 2026 03:31:37 +0800 Subject: [PATCH 10/33] =?UTF-8?q?=E8=A7=A3=E5=86=B3=E5=85=A8=E5=B1=80=20da?= =?UTF-8?q?tasource,=20namespace,=20catalog=20=E6=9C=AA=E7=94=A8=E4=BA=8E?= =?UTF-8?q?=E5=8F=82=E6=95=B0=E6=A0=A1=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- APIJSONORM/pom.xml | 2 +- APIJSONORM/src/main/java/apijson/Log.java | 2 +- .../main/java/apijson/orm/AbstractParser.java | 18 ++- .../java/apijson/orm/AbstractSQLConfig.java | 39 +++++-- .../java/apijson/orm/AbstractVerifier.java | 108 +++++++++++------- .../src/main/java/apijson/orm/Verifier.java | 15 ++- 6 files changed, 118 insertions(+), 66 deletions(-) diff --git a/APIJSONORM/pom.xml b/APIJSONORM/pom.xml index 4ce8f9af..5f869837 100644 --- a/APIJSONORM/pom.xml +++ b/APIJSONORM/pom.xml @@ -5,7 +5,7 @@ com.github.Tencent APIJSON - 8.1.5 + 8.1.6 jar APIJSONORM diff --git a/APIJSONORM/src/main/java/apijson/Log.java b/APIJSONORM/src/main/java/apijson/Log.java index d301cdf0..5a4d2169 100755 --- a/APIJSONORM/src/main/java/apijson/Log.java +++ b/APIJSONORM/src/main/java/apijson/Log.java @@ -21,7 +21,7 @@ public class Log { public static String LEVEL = LEVEL_WARN; - public static final String VERSION = "8.1.5"; + public static final String VERSION = "8.1.6"; public static final String KEY_SYSTEM_INFO_DIVIDER = "\n---|-----APIJSON SYSTEM INFO-----|---\n"; public static final String OS_NAME; diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java b/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java index e2403122..44550abe 100755 --- a/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java +++ b/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java @@ -1516,10 +1516,10 @@ else if (childKeys.length == 1 && isTableKey(childKeys[0])) { // 可能无需 JOIN_COPY_KEY_LIST = new ArrayList(); JOIN_COPY_KEY_LIST.add(KEY_ROLE); JOIN_COPY_KEY_LIST.add(KEY_DATABASE); + JOIN_COPY_KEY_LIST.add(KEY_DATASOURCE); JOIN_COPY_KEY_LIST.add(KEY_NAMESPACE); JOIN_COPY_KEY_LIST.add(KEY_CATALOG); JOIN_COPY_KEY_LIST.add(KEY_SCHEMA); - JOIN_COPY_KEY_LIST.add(KEY_DATASOURCE); JOIN_COPY_KEY_LIST.add(KEY_COLUMN); JOIN_COPY_KEY_LIST.add(KEY_NULL); JOIN_COPY_KEY_LIST.add(KEY_CAST); @@ -2382,9 +2382,11 @@ protected M batchVerify(RequestMethod method, String tag, int version, String na } switch (objAttrKey) { + case KEY_DATABASE: case KEY_DATASOURCE: + case KEY_NAMESPACE: + case KEY_CATALOG: case KEY_SCHEMA: - case KEY_DATABASE: case KEY_VERSION: case KEY_ROLE: objAttrMap.put(objAttrKey, entry.getValue()); @@ -2432,17 +2434,21 @@ protected M batchVerify(RequestMethod method, String tag, int version, String na } } else { setRequestAttribute(key, true, KEY_METHOD, request); + setRequestAttribute(key, true, KEY_DATABASE, request); setRequestAttribute(key, true, KEY_DATASOURCE, request); + setRequestAttribute(key, true, KEY_NAMESPACE, request); + setRequestAttribute(key, true, KEY_CATALOG, request); setRequestAttribute(key, true, KEY_SCHEMA, request); - setRequestAttribute(key, true, KEY_DATABASE, request); setRequestAttribute(key, true, KEY_VERSION, request); setRequestAttribute(key, true, KEY_ROLE, request); } } else { setRequestAttribute(key, false, KEY_METHOD, request); + setRequestAttribute(key, false, KEY_DATABASE, request); setRequestAttribute(key, false, KEY_DATASOURCE, request); + setRequestAttribute(key, false, KEY_NAMESPACE, request); + setRequestAttribute(key, false, KEY_CATALOG, request); setRequestAttribute(key, false, KEY_SCHEMA, request); - setRequestAttribute(key, false, KEY_DATABASE, request); setRequestAttribute(key, false, KEY_VERSION, request); setRequestAttribute(key, false, KEY_ROLE, request); } @@ -2569,7 +2575,9 @@ protected M objectVerify(RequestMethod method, String tag, int version, String n // 获取指定的JSON结构 >>>>>>>>>>>>>> M target = wrapRequest(method, tag, object, true); // Map clone 浅拷贝没用,Structure.parse 会导致 structure 里面被清空,第二次从缓存里取到的就是 {} - return getVerifier().setParser(this).verifyRequest(method, name, target, request, maxUpdateCount, getGlobalDatabase(), getGlobalSchema()); + return getVerifier().setParser(this).verifyRequest(method, name, target, request, maxUpdateCount + , getGlobalDatabase(), getGlobalDatasource(), getGlobalNamespace(), getGlobalCatalog(), getGlobalSchema() + ); } /*** diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java b/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java index d9e9eb01..c3532314 100755 --- a/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java +++ b/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java @@ -5490,7 +5490,7 @@ public static , L extends List> SQLConf String catalog = getString(request, KEY_CATALOG); String schema = getString(request, KEY_SCHEMA); - SQLConfig config = (SQLConfig) callback.getSQLConfig(method, database, schema, datasource, table); + SQLConfig config = (SQLConfig) callback.getSQLConfig(method, database, datasource, namespace, catalog, schema, table); config.setAlias(alias); config.setDatabase(database); // 不删,后面表对象还要用的,必须放在 parseJoin 前 @@ -5511,9 +5511,9 @@ public static , L extends List> SQLConf // 对 id, id{}, userId, userId{} 处理,这些只要不为 null 就一定会作为 AND 条件 <<<<<<<<<<<<<<<<<<<<<<<<< - String idKey = callback.getIdKey(datasource, database, schema, table); + String idKey = callback.getIdKey(database, datasource, namespace, catalog, schema, table); String idInKey = idKey + "{}"; - String userIdKey = callback.getUserIdKey(datasource, database, schema, table); + String userIdKey = callback.getUserIdKey(database, datasource, namespace, catalog, schema, table); String userIdInKey = userIdKey + "{}"; Object idIn = request.get(idInKey); // 可能是 id{}:">0" @@ -5539,7 +5539,7 @@ public static , L extends List> SQLConf Object id = request.get(idKey); if (id == null && method == POST) { - id = callback.newId(method, database, schema, datasource, table); // null 表示数据库自增 id + id = callback.newId(method, database, datasource, namespace, catalog, schema, table); // null 表示数据库自增 id } if (id != null) { // null 无效 @@ -6532,44 +6532,59 @@ public static interface IdCallback { /**为 post 请求新建 id, 只能是 Long 或 String * @param method * @param database + * @param datasource + * @param namespace + * @param catalog * @param schema * @param table * @return */ - T newId(RequestMethod method, String database, String schema, String datasource, String table); + T newId(RequestMethod method, String database, String datasource, String namespace, String catalog, String schema, String table); /**获取主键名 * @param database + * @param datasource + * @param namespace + * @param catalog * @param schema * @param table * @return */ - String getIdKey(String database, String schema, String datasource, String table); + String getIdKey(String database, String datasource, String namespace, String catalog, String schema, String table); /**获取 User 的主键名 * @param database + * @param datasource + * @param namespace + * @param catalog * @param schema * @param table * @return */ - String getUserIdKey(String database, String schema, String datasource, String table); + String getUserIdKey(String database, String datasource, String namespace, String catalog, String schema, String table); } public static interface Callback, L extends List> extends IdCallback { /**获取 SQLConfig 的实例 * @param method * @param database + * @param datasource + * @param namespace + * @param catalog * @param schema * @param table * @return */ - SQLConfig getSQLConfig(RequestMethod method, String database, String schema, String datasource, String table); + SQLConfig getSQLConfig(RequestMethod method, String database, String datasource, String namespace, String catalog, String schema, String table); /**combine 里的 key 在 request 中 value 为 null 或不存在,即 request 中缺少用来作为 combine 条件的 key: value + * @param name + * @param request * @param combine + * @param item * @param key - * @param request + * @throws Exception */ void onMissingKey4Combine(String name, M request, String combine, String item, String key) throws Exception; } @@ -6583,7 +6598,7 @@ public static abstract class SimpleCallback, L @SuppressWarnings("unchecked") @Override - public T newId(RequestMethod method, String database, String schema, String datasource, String table) { + public T newId(RequestMethod method, String database, String datasource, String namespace, String catalog, String schema, String table) { Long id = System.currentTimeMillis(); if (id <= LAST_ID) { id = LAST_ID + 1; // 解决高并发下 id 冲突导致新增记录失败 @@ -6594,12 +6609,12 @@ public T newId(RequestMethod method, String database, String schema, String data } @Override - public String getIdKey(String database, String schema, String datasource, String table) { + public String getIdKey(String database, String datasource, String namespace, String catalog, String schema, String table) { return KEY_ID; } @Override - public String getUserIdKey(String database, String schema, String datasource, String table) { + public String getUserIdKey(String database, String datasource, String namespace, String catalog, String schema, String table) { return KEY_USER_ID; } diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractVerifier.java b/APIJSONORM/src/main/java/apijson/orm/AbstractVerifier.java index 5e665815..09e9b4f3 100755 --- a/APIJSONORM/src/main/java/apijson/orm/AbstractVerifier.java +++ b/APIJSONORM/src/main/java/apijson/orm/AbstractVerifier.java @@ -209,21 +209,21 @@ public static HashMap getAccessMap(MethodAccess access) @Override public String getVisitorIdKey(SQLConfig config) { - return config == null ? getUserIdKey(null, null, null, null) : config.getUserIdKey(); + return config == null ? getUserIdKey(null, null, null, null, null, null) : config.getUserIdKey(); } @Override - public String getIdKey(String database, String schema, String datasource, String table) { + public String getIdKey(String database, String datasource, String namespace, String catalog, String schema, String table) { return KEY_ID; } @Override - public String getUserIdKey(String database, String schema, String datasource, String table) { + public String getUserIdKey(String database, String datasource, String namespace, String catalog, String schema, String table) { return KEY_USER_ID; } @SuppressWarnings("unchecked") @Override - public T newId(RequestMethod method, String database, String schema, String datasource, String table) { + public T newId(RequestMethod method, String database, String datasource, String namespace, String catalog, String schema, String table) { return (T) Long.valueOf(System.currentTimeMillis()); } @@ -555,9 +555,9 @@ public void verifyRepeat(String table, String key, Object value, long exceptId) * @throws Exception */ @Override - public M verifyRequest(@NotNull final RequestMethod method, final String name, final M target, final M request, final int maxUpdateCount - , final String database, final String schema) throws Exception { - return verifyRequest(method, name, target, request, maxUpdateCount, database, schema, this, getParser()); + public M verifyRequest(@NotNull RequestMethod method, String name, M target, M request, int maxUpdateCount + , String database, String datasource, String namespace, String catalog, String schema) throws Exception { + return verifyRequest(method, name, target, request, maxUpdateCount, database, datasource, null, null, schema, this, getParser()); } /**从request提取target指定的内容 @@ -609,27 +609,32 @@ public static , L extends List> M verif @NotNull RequestMethod method, String name, M target, M request, int maxUpdateCount, String database , String schema, IdCallback idCallback, @NotNull Parser parser) throws Exception { - return verifyRequest(method, name, target, request, maxUpdateCount, database, schema, null, idCallback, parser); + return verifyRequest(method, name, target, request, maxUpdateCount, database, null, null, null, schema, idCallback, parser); } /**从request提取target指定的内容 - * @param method - * @param name - * @param target - * @param request - * @param maxUpdateCount - * @param database - * @param schema - * @param datasource - * @param idCallback - * @param parser - * @return - * @param - * @throws Exception - */ + * @param method + * @param name + * @param target + * @param request + * @param maxUpdateCount + * @param database + * @param datasource + * @param namespace + * @param catalog + * @param schema + * @param idCallback + * @param parser + * @return + * @param + * @param + * @param + * @throws Exception + */ public static , L extends List> M verifyRequest( @NotNull final RequestMethod method, final String name, final M target, final M request - , final int maxUpdateCount, final String database, final String schema, final String datasource - , final IdCallback idCallback, @NotNull Parser parser) throws Exception { + , final int maxUpdateCount, final String database, final String datasource, final String namespace + , final String catalog, final String schema, final IdCallback idCallback + , @NotNull Parser parser) throws Exception { if (ENABLE_VERIFY_CONTENT == false) { throw new UnsupportedOperationException("AbstractVerifier.ENABLE_VERIFY_CONTENT == false" + " 时不支持校验请求传参内容!如需支持则设置 AbstractVerifier.ENABLE_VERIFY_CONTENT = true !"); @@ -652,7 +657,7 @@ public static , L extends List> M verif //解析 - return parse(method, name, target, request, database, schema, idCallback, parser, new OnParseCallback() { + return parse(method, name, target, request, database, datasource, namespace, catalog, schema, idCallback, parser, new OnParseCallback() { @Override public M onParseJSONObject(String key, M tobj, M robj) throws Exception { @@ -664,19 +669,27 @@ public M onParseJSONObject(String key, M tobj, M robj) throws Exception { } } else if (isTableKey(key)) { String db = getString(request, KEY_DATABASE); - String sh = getString(request, KEY_SCHEMA); String ds = getString(request, KEY_DATASOURCE); + String ns = getString(request, KEY_NAMESPACE); + String cl = getString(request, KEY_CATALOG); + String sh = getString(request, KEY_SCHEMA); if (StringUtil.isEmpty(db, false)) { db = database; } - if (StringUtil.isEmpty(sh, false)) { - sh = schema; - } if (StringUtil.isEmpty(ds, false)) { ds = datasource; } + if (StringUtil.isEmpty(ns, false)) { + ns = namespace; + } + if (StringUtil.isEmpty(cl, false)) { + cl = catalog; + } + if (StringUtil.isEmpty(sh, false)) { + sh = schema; + } - String idKey = idCallback == null ? null : idCallback.getIdKey(db, sh, ds, key); + String idKey = idCallback == null ? null : idCallback.getIdKey(db, ds, ns, cl, sh, key); String finalIdKey = StringUtil.isEmpty(idKey, false) ? KEY_ID : idKey; if (method == POST) { @@ -688,14 +701,14 @@ public M onParseJSONObject(String key, M tobj, M robj) throws Exception { if (Boolean.TRUE.equals(atLeastOne) || RequestMethod.isUpdateMethod(method)) { verifyId(method.name(), name, key, robj, finalIdKey, maxUpdateCount, atLeastOne != null ? atLeastOne : IS_UPDATE_MUST_HAVE_ID_CONDITION); - String userIdKey = idCallback == null ? null : idCallback.getUserIdKey(db, sh, ds, key); + String userIdKey = idCallback == null ? null : idCallback.getUserIdKey(db, ds, ns, cl, sh, key); String finalUserIdKey = StringUtil.isEmpty(userIdKey, false) ? KEY_USER_ID : userIdKey; verifyId(method.name(), name, key, robj, finalUserIdKey, maxUpdateCount, false); } } } - return verifyRequest(method, key, tobj, robj, maxUpdateCount, database, schema, idCallback, parser); + return verifyRequest(method, key, tobj, robj, maxUpdateCount, database, datasource, namespace, catalog, schema, idCallback, parser); } @Override @@ -888,7 +901,7 @@ public static , L extends List> M parse public static , L extends List> M parse( @NotNull final RequestMethod method, String name, M target, M real, final String database, final String schema , final IdCallback idCallback, @NotNull Parser parser, @NotNull OnParseCallback callback) throws Exception { - return parse(method, name, target, real, database, schema, null, idCallback, parser, callback); + return parse(method, name, target, real, database, null, null, null, schema, idCallback, parser, callback); } /**对request和response不同的解析用callback返回 * @param method @@ -896,16 +909,21 @@ public static , L extends List> M parse * @param target * @param real * @param database - * @param schema * @param datasource + * @param namespace + * @param catalog + * @param schema * @param idCallback * @param parser * @param callback * @return + * @param + * @param + * @param * @throws Exception */ public static , L extends List> M parse(@NotNull final RequestMethod method - , String name, M target, M real, final String database, final String schema, final String datasource + , String name, M target, M real, String database, String datasource, String namespace, String catalog, String schema , final IdCallback idCallback, @NotNull Parser parser, @NotNull OnParseCallback callback) throws Exception { if (target == null) { return null; @@ -1153,18 +1171,26 @@ && rv instanceof List && isArrayKey(rk)) { String db = getString(real, KEY_DATABASE); - String sh = getString(real, KEY_SCHEMA); String ds = getString(real, KEY_DATASOURCE); + String ns = getString(real, KEY_NAMESPACE); + String cl = getString(real, KEY_CATALOG); + String sh = getString(real, KEY_SCHEMA); if (StringUtil.isEmpty(db, false)) { db = database; } - if (StringUtil.isEmpty(sh, false)) { - sh = schema; - } if (StringUtil.isEmpty(ds, false)) { ds = datasource; } - String idKey = idCallback == null ? null : idCallback.getIdKey(db, sh, ds, name); + if (StringUtil.isEmpty(ns, false)) { + ns = namespace; + } + if (StringUtil.isEmpty(cl, false)) { + cl = catalog; + } + if (StringUtil.isEmpty(sh, false)) { + sh = schema; + } + String idKey = idCallback == null ? null : idCallback.getIdKey(db, ds, ns, cl, sh, name); String finalIdKey = StringUtil.isEmpty(idKey, false) ? KEY_ID : idKey; // TODO 放在operate前?考虑性能、operate修改后再验证的值是否和原来一样 @@ -1298,7 +1324,7 @@ && rv instanceof List && isArrayKey(rk)) { } if (nkl.contains(k) || real.get(k) != null) { - real = parse(method, name, (M) v, real, database, schema, datasource, idCallback, parser, callback); + real = parse(method, name, (M) v, real, database, datasource, namespace, catalog, schema, idCallback, parser, callback); } } } diff --git a/APIJSONORM/src/main/java/apijson/orm/Verifier.java b/APIJSONORM/src/main/java/apijson/orm/Verifier.java index 4b926519..97db58a9 100755 --- a/APIJSONORM/src/main/java/apijson/orm/Verifier.java +++ b/APIJSONORM/src/main/java/apijson/orm/Verifier.java @@ -69,14 +69,17 @@ public interface Verifier, L extends List Date: Sat, 18 Apr 2026 04:15:04 +0800 Subject: [PATCH 11/33] =?UTF-8?q?=E8=A7=A3=E5=86=B3=E5=85=A8=E5=B1=80=20na?= =?UTF-8?q?mespace,=20catalog=20=E6=9C=AA=E7=94=A8=E4=BA=8E=E5=8F=82?= =?UTF-8?q?=E6=95=B0=E6=A0=A1=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- APIJSONORM/src/main/java/apijson/orm/AbstractVerifier.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractVerifier.java b/APIJSONORM/src/main/java/apijson/orm/AbstractVerifier.java index 09e9b4f3..9824d488 100755 --- a/APIJSONORM/src/main/java/apijson/orm/AbstractVerifier.java +++ b/APIJSONORM/src/main/java/apijson/orm/AbstractVerifier.java @@ -557,7 +557,7 @@ public void verifyRepeat(String table, String key, Object value, long exceptId) @Override public M verifyRequest(@NotNull RequestMethod method, String name, M target, M request, int maxUpdateCount , String database, String datasource, String namespace, String catalog, String schema) throws Exception { - return verifyRequest(method, name, target, request, maxUpdateCount, database, datasource, null, null, schema, this, getParser()); + return verifyRequest(method, name, target, request, maxUpdateCount, database, datasource, namespace, catalog, schema, this, getParser()); } /**从request提取target指定的内容 From 0fe9692113b2f67678d56e1a9d07afd6e9189275 Mon Sep 17 00:00:00 2001 From: TommyLemon Date: Sat, 18 Apr 2026 04:59:22 +0800 Subject: [PATCH 12/33] =?UTF-8?q?=E8=A7=A3=E5=86=B3=E6=A0=A1=E9=AA=8C?= =?UTF-8?q?=E5=8F=82=E6=95=B0=E6=8B=BF=E4=B8=8D=E5=88=B0=20datasource,=20n?= =?UTF-8?q?amespace,=20catalog=20=E7=AD=89=E5=85=A8=E5=B1=80=E5=85=B3?= =?UTF-8?q?=E9=94=AE=E8=AF=8D=E5=8F=96=E5=80=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../apijson/orm/AbstractObjectParser.java | 4 +- .../main/java/apijson/orm/AbstractParser.java | 44 +++++++++---------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractObjectParser.java b/APIJSONORM/src/main/java/apijson/orm/AbstractObjectParser.java index c49c9cd2..c4f7c5ff 100755 --- a/APIJSONORM/src/main/java/apijson/orm/AbstractObjectParser.java +++ b/APIJSONORM/src/main/java/apijson/orm/AbstractObjectParser.java @@ -720,7 +720,7 @@ public void onPUTArrayParse(@NotNull String key, @NotNull L array) throws Except if (apijson.JSON.isBoolOrNumOrStr(target)) { throw new NullPointerException("PUT " + path + ", " + realKey + " 类型为 " + target.getClass().getSimpleName() + "," + "不支持 Boolean, String, Number 等类型字段使用 'key+': [] 或 'key-': [] !" - + "对应字段在数据库的值必须为 L, JSONRequest 中的一种!" + + "对应字段在数据库的值必须为 JSONArray, JSONObject 中的一种!" + "值为 JSONRequest 类型时传参必须是 'key+': [{'key': value, 'key2': value2}] 或 'key-': ['key', 'key2'] !" ); } @@ -734,7 +734,7 @@ public void onPUTArrayParse(@NotNull String key, @NotNull L array) throws Except if (isAdd == false) { throw new NullPointerException("PUT " + path + ", " + realKey + (target == null ? " 值为 null,不支持移除!" : " 类型为 " + target.getClass().getSimpleName() + ",不支持这样移除!") - + "对应字段在数据库的值必须为 L, JSONRequest 中的一种,且 key- 移除时,本身的值不能为 null!" + + "对应字段在数据库的值必须为 JSONArray, JSONObject 中的一种,且 key- 移除时,本身的值不能为 null!" + "值为 JSONRequest 类型时传参必须是 'key+': [{'key': value, 'key2': value2}] 或 'key-': ['key', 'key2'] !" ); } diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java b/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java index 44550abe..defccc93 100755 --- a/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java +++ b/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java @@ -527,6 +527,28 @@ public M parseResponse(M request) { return extendErrorResult(requestObject, e, requestMethod, getRequestURL(), isRoot); } + try { + setGlobalDatabase(getString(requestObject, KEY_DATABASE)); + setGlobalDatasource(getString(requestObject, KEY_DATASOURCE)); + setGlobalNamespace(getString(requestObject, KEY_NAMESPACE)); + setGlobalCatalog(getString(requestObject, KEY_CATALOG)); + setGlobalSchema(getString(requestObject, KEY_SCHEMA)); + + setGlobalExplain(getBoolean(requestObject, KEY_EXPLAIN)); + setGlobalCache(getString(requestObject, KEY_CACHE)); + + requestObject.remove(KEY_DATABASE); + requestObject.remove(KEY_DATASOURCE); + requestObject.remove(KEY_NAMESPACE); + requestObject.remove(KEY_CATALOG); + requestObject.remove(KEY_SCHEMA); + + requestObject.remove(KEY_EXPLAIN); + requestObject.remove(KEY_CACHE); + } catch (Exception e) { + return extendErrorResult(requestObject, e, requestMethod, getRequestURL(), isRoot); + } + verifier = createVerifier().setVisitor(getVisitor()); if (RequestMethod.isPublicMethod(requestMethod) == false) { @@ -552,28 +574,6 @@ public M parseResponse(M request) { } } - try { - setGlobalDatabase(getString(requestObject, KEY_DATABASE)); - setGlobalDatasource(getString(requestObject, KEY_DATASOURCE)); - setGlobalNamespace(getString(requestObject, KEY_NAMESPACE)); - setGlobalCatalog(getString(requestObject, KEY_CATALOG)); - setGlobalSchema(getString(requestObject, KEY_SCHEMA)); - - setGlobalExplain(getBoolean(requestObject, KEY_EXPLAIN)); - setGlobalCache(getString(requestObject, KEY_CACHE)); - - requestObject.remove(KEY_DATABASE); - requestObject.remove(KEY_DATASOURCE); - requestObject.remove(KEY_NAMESPACE); - requestObject.remove(KEY_CATALOG); - requestObject.remove(KEY_SCHEMA); - - requestObject.remove(KEY_EXPLAIN); - requestObject.remove(KEY_CACHE); - } catch (Exception e) { - return extendErrorResult(requestObject, e, requestMethod, getRequestURL(), isRoot); - } - final String requestString = JSON.toJSONString(request);//request传进去解析后已经变了 queryResultMap = new HashMap(); From c06fc789c5888d518b826b49d33377c28337382f Mon Sep 17 00:00:00 2001 From: willingqin Date: Sat, 18 Apr 2026 08:51:43 +0800 Subject: [PATCH 13/33] add readme --- README-Chinese.md | 105 ---------------------------------------------- README.md | 85 ------------------------------------- 2 files changed, 190 deletions(-) diff --git a/README-Chinese.md b/README-Chinese.md index ceb1ef25..f6ec53cf 100644 --- a/README-Chinese.md +++ b/README-Chinese.md @@ -376,116 +376,11 @@ https://github.com/Tencent/APIJSON/issues/187 ### 贡献者们 主项目 APIJSON 的贡献者们(6 个腾讯工程师、1 个微软工程师、1 个阿里云工程师、1 个字节跳动工程师、1 个网易工程师、1 个 Zoom 工程师、1 个圆通工程师、1 个知乎基础研发架构师、1 个智联招聘工程师、gorm-plus 作者、1 个美国加州大学学生、3 个 SUSTech 学生等):
https://github.com/Tencent/APIJSON/blob/master/CONTRIBUTING.md
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

生态周边项目的作者们(2 个腾讯工程师、1 个 BAT 技术专家、1 个微软工程师、2 个字节跳动工程师、1 个神州数码工程师&Apache dubbo2js 作者 等):
https://github.com/search?o=desc&q=apijson&s=stars&type=Repositories
https://search.gitee.com/?skin=rec&type=repository&q=apijson&sort=stars_count
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

还有为 APIJSON 扫描代码贡献 Issue 的 [蚂蚁集团源伞](https://www.sourcebrella.com) 和 [奇安信代码卫士](https://github.com/QiAnXinCodeSafe) diff --git a/README.md b/README.md index 8811a3bd..462d4df1 100644 --- a/README.md +++ b/README.md @@ -301,96 +301,11 @@ https://github.com/Tencent/APIJSON/issues/187 ### Contributers of APIJSON: Contributers for the APIJSON core project(6 Tencent engineers, 1 Microsoft engineer, 1 Zhihu architect, 1 Bytedance(TikTok) engineer, 1 NetEase engineer, 1 Zoom engineer, 1 YTO Express engineer, 1 Zhilian engineer, 1 UC student、3 SUSTech students, etc.):
https://github.com/Tencent/APIJSON/blob/master/CONTRIBUTING.md
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Authors of other projects for ecosystem of APIJSON(2 Tencent engineers, 1 BAT(Baidu/Alibaba/Tencent) expert, 1 Microsoft engineer, 2 Bytedance(TikTok) engineers, 1 Digital China engineer & Apache dubbo2js author, etc.):
https://github.com/search?o=desc&q=apijson&s=stars&type=Repositories
https://search.gitee.com/?skin=rec&type=repository&q=apijson&sort=stars_count
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Thanks to all contributers of APIJSON! From 3462f0174f751fa2753e159cced33f3a0d9c993a Mon Sep 17 00:00:00 2001 From: TommyLemon <1184482681@qq.com> Date: Sat, 18 Apr 2026 11:51:36 +0800 Subject: [PATCH 14/33] =?UTF-8?q?=E6=8A=8A=20Gitee=20=E4=B8=8A=E6=AD=A3?= =?UTF-8?q?=E5=B8=B8=E6=98=BE=E7=A4=BA=E7=9A=84=E8=B4=A1=E7=8C=AE=E8=80=85?= =?UTF-8?q?=E5=92=8C=E4=BD=9C=E8=80=85=E5=A4=B4=E5=83=8F=E4=B8=80=E8=B5=B7?= =?UTF-8?q?=E6=88=AA=E5=B1=8F=E6=9D=A5=E5=A1=AB=E8=A1=A5=E7=A7=BB=E9=99=A4?= =?UTF-8?q?=E7=9A=84=E5=8D=95=E4=B8=AA=E5=A4=B4=E5=83=8F=E9=9B=86=E5=90=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 462d4df1..f6c637fd 100644 --- a/README.md +++ b/README.md @@ -302,11 +302,13 @@ https://github.com/Tencent/APIJSON/issues/187 Contributers for the APIJSON core project(6 Tencent engineers, 1 Microsoft engineer, 1 Zhihu architect, 1 Bytedance(TikTok) engineer, 1 NetEase engineer, 1 Zoom engineer, 1 YTO Express engineer, 1 Zhilian engineer, 1 UC student、3 SUSTech students, etc.):
https://github.com/Tencent/APIJSON/blob/master/CONTRIBUTING.md

- +Screenshot 2026-04-18 at 05 28 48 + Authors of other projects for ecosystem of APIJSON(2 Tencent engineers, 1 BAT(Baidu/Alibaba/Tencent) expert, 1 Microsoft engineer, 2 Bytedance(TikTok) engineers, 1 Digital China engineer & Apache dubbo2js author, etc.):
https://github.com/search?o=desc&q=apijson&s=stars&type=Repositories
https://search.gitee.com/?skin=rec&type=repository&q=apijson&sort=stars_count

+Screenshot 2026-04-18 at 05 29 36 Thanks to all contributers of APIJSON! From 2ce8ad1708ea27293036feaad8c9c9d0dc8498e4 Mon Sep 17 00:00:00 2001 From: TommyLemon <1184482681@qq.com> Date: Sat, 18 Apr 2026 12:23:24 +0800 Subject: [PATCH 15/33] =?UTF-8?q?=E6=8A=8A=20Gitee=20=E4=B8=8A=E6=AD=A3?= =?UTF-8?q?=E5=B8=B8=E6=98=BE=E7=A4=BA=E7=9A=84=E8=B4=A1=E7=8C=AE=E8=80=85?= =?UTF-8?q?=E5=92=8C=E4=BD=9C=E8=80=85=E5=A4=B4=E5=83=8F=E4=B8=80=E8=B5=B7?= =?UTF-8?q?=E6=88=AA=E5=B1=8F=E6=9D=A5=E5=A1=AB=E8=A1=A5=E7=A7=BB=E9=99=A4?= =?UTF-8?q?=E7=9A=84=E5=8D=95=E4=B8=AA=E5=A4=B4=E5=83=8F=E9=9B=86=E5=90=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README-Chinese.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README-Chinese.md b/README-Chinese.md index f6ec53cf..3e9b446f 100644 --- a/README-Chinese.md +++ b/README-Chinese.md @@ -377,11 +377,13 @@ https://github.com/Tencent/APIJSON/issues/187 主项目 APIJSON 的贡献者们(6 个腾讯工程师、1 个微软工程师、1 个阿里云工程师、1 个字节跳动工程师、1 个网易工程师、1 个 Zoom 工程师、1 个圆通工程师、1 个知乎基础研发架构师、1 个智联招聘工程师、gorm-plus 作者、1 个美国加州大学学生、3 个 SUSTech 学生等):
https://github.com/Tencent/APIJSON/blob/master/CONTRIBUTING.md

+Screenshot 2026-04-18 at 05 28 48 生态周边项目的作者们(2 个腾讯工程师、1 个 BAT 技术专家、1 个微软工程师、2 个字节跳动工程师、1 个神州数码工程师&Apache dubbo2js 作者 等):
https://github.com/search?o=desc&q=apijson&s=stars&type=Repositories
https://search.gitee.com/?skin=rec&type=repository&q=apijson&sort=stars_count

+Screenshot 2026-04-18 at 05 29 36 还有为 APIJSON 扫描代码贡献 Issue 的 [蚂蚁集团源伞](https://www.sourcebrella.com) 和 [奇安信代码卫士](https://github.com/QiAnXinCodeSafe)
From f31e5858d57bbda980b5392cfb61530056d76e75 Mon Sep 17 00:00:00 2001 From: TommyLemon <1184482681@qq.com> Date: Tue, 5 May 2026 21:44:58 +0800 Subject: [PATCH 16/33] =?UTF-8?q?=E7=94=9F=E6=80=81=E9=A1=B9=E7=9B=AE?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=20APIJSONServer=20-=20=E5=9F=BA=E4=BA=8EAPIJ?= =?UTF-8?q?SON=E5=AE=9E=E7=8E=B0=E7=9A=84=E6=95=B0=E6=8D=AE=E6=9C=8D?= =?UTF-8?q?=E5=8A=A1=E7=AB=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 感谢 @cyber2jie 的贡献,创作不易,点亮 ⭐️ Star 收藏/支持下吧 ^_^ https://github.com/cyber2jie/APIJSONServer --- README-Chinese.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README-Chinese.md b/README-Chinese.md index 3e9b446f..8fd9e98c 100644 --- a/README-Chinese.md +++ b/README-Chinese.md @@ -662,6 +662,8 @@ Issue/问卷 一般解答顺序:贡献者 > 帮助他人的用户 > 提供任 [apijson-spring-boot](https://gitee.com/yunjiao-source/apijson-spring-boot) Springboot3 for APIJSON,用 YAML 简化代码配置 +[APIJSONServer](https://github.com/cyber2jie/APIJSONServer) 基于APIJSON实现的数据服务端 + 感谢热心的作者们的贡献,点 ⭐Star 支持下他们吧~ From c26c64c8ee3ca5c298e36286f745d94b5d2288de Mon Sep 17 00:00:00 2001 From: TommyLemon Date: Mon, 11 May 2026 04:42:41 +0800 Subject: [PATCH 17/33] =?UTF-8?q?=E9=9D=9E=20DEBUG=20=E6=A8=A1=E5=BC=8F?= =?UTF-8?q?=E4=B8=8D=E5=85=81=E8=AE=B8=E5=A4=96=E9=83=A8=E6=93=8D=E4=BD=9C?= =?UTF-8?q?=20APIJSON=20=E9=85=8D=E7=BD=AE=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- APIJSONORM/pom.xml | 2 +- APIJSONORM/src/main/java/apijson/Log.java | 2 +- APIJSONORM/src/main/java/apijson/orm/AbstractVerifier.java | 6 +++++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/APIJSONORM/pom.xml b/APIJSONORM/pom.xml index 5f869837..fb050e32 100644 --- a/APIJSONORM/pom.xml +++ b/APIJSONORM/pom.xml @@ -5,7 +5,7 @@ com.github.Tencent APIJSON - 8.1.6 + 8.1.7 jar APIJSONORM diff --git a/APIJSONORM/src/main/java/apijson/Log.java b/APIJSONORM/src/main/java/apijson/Log.java index 5a4d2169..e4bd7ba7 100755 --- a/APIJSONORM/src/main/java/apijson/Log.java +++ b/APIJSONORM/src/main/java/apijson/Log.java @@ -21,7 +21,7 @@ public class Log { public static String LEVEL = LEVEL_WARN; - public static final String VERSION = "8.1.6"; + public static final String VERSION = "8.1.7"; public static final String KEY_SYSTEM_INFO_DIVIDER = "\n---|-----APIJSON SYSTEM INFO-----|---\n"; public static final String OS_NAME; diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractVerifier.java b/APIJSONORM/src/main/java/apijson/orm/AbstractVerifier.java index 9824d488..f0257030 100755 --- a/APIJSONORM/src/main/java/apijson/orm/AbstractVerifier.java +++ b/APIJSONORM/src/main/java/apijson/orm/AbstractVerifier.java @@ -108,7 +108,7 @@ public abstract class AbstractVerifier, L exten // > // > @NotNull - public static Map> SYSTEM_ACCESS_MAP; + public static Map> SYSTEM_ACCESS_MAP; // TODO 改名为 CONFIG_ACCESS_MAP ? @NotNull public static Map> ACCESS_MAP; @NotNull @@ -319,6 +319,10 @@ public void verifyAllowRole(SQLConfig config, String table, RequestMeth role = config == null ? UNKNOWN : config.getRole(); } + if (Log.DEBUG == false && SYSTEM_ACCESS_MAP.get(table) != null) { + throw new IllegalAccessException(table + " 不允许 " + role + " 用户的 " + method.name() + " 请求!"); + } + Map map = ACCESS_MAP.get(table); if (map == null || Arrays.asList(map.get(method)).contains(role) == false) { From 699f78d83196c4e49d14c456638a00ec210a4691 Mon Sep 17 00:00:00 2001 From: TommyLemon <1184482681@qq.com> Date: Sat, 16 May 2026 01:17:01 +0800 Subject: [PATCH 18/33] Update AbstractFunctionParser.java --- .../src/main/java/apijson/orm/AbstractFunctionParser.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractFunctionParser.java b/APIJSONORM/src/main/java/apijson/orm/AbstractFunctionParser.java index 42831775..ac0cc308 100755 --- a/APIJSONORM/src/main/java/apijson/orm/AbstractFunctionParser.java +++ b/APIJSONORM/src/main/java/apijson/orm/AbstractFunctionParser.java @@ -33,7 +33,7 @@ public abstract class AbstractFunctionParser, L public static boolean ENABLE_REMOTE_FUNCTION = true; /**开启支持远程函数中的 JavaScript 脚本形式 */ - public static boolean ENABLE_SCRIPT_FUNCTION = true; + public static boolean ENABLE_SCRIPT_FUNCTION = false; // // > @@ -961,4 +961,4 @@ public V getArgVal(String key, Class clazz, boolean defaultValue) throws } } -} \ No newline at end of file +} From b11b822808ab532116897616d7da13156626b74e Mon Sep 17 00:00:00 2001 From: TommyLemon Date: Sat, 16 May 2026 22:16:02 +0800 Subject: [PATCH 19/33] Update AbstractVerifier.java --- APIJSONORM/src/main/java/apijson/orm/AbstractVerifier.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractVerifier.java b/APIJSONORM/src/main/java/apijson/orm/AbstractVerifier.java index f0257030..81ccc1ee 100755 --- a/APIJSONORM/src/main/java/apijson/orm/AbstractVerifier.java +++ b/APIJSONORM/src/main/java/apijson/orm/AbstractVerifier.java @@ -14,6 +14,7 @@ import static apijson.RequestMethod.HEADS; import static apijson.RequestMethod.POST; import static apijson.RequestMethod.PUT; +import static apijson.orm.AbstractFunctionParser.ENABLE_SCRIPT_FUNCTION; import static apijson.orm.Operation.*; //import static apijson.orm.Operation.CODE; @@ -1339,6 +1340,11 @@ && rv instanceof List && isArrayKey(rk)) { } public static ScriptEngine getScriptEngine(String lang) { + if (ENABLE_SCRIPT_FUNCTION == false) { + throw new UnsupportedOperationException("AbstractFunctionParser.ENABLE_SCRIPT_FUNCTION" + + " == false 时不支持执行脚本!如需支持则设置为 true !"); + } + boolean isEmpty = StringUtil.isEmpty(lang, true); ScriptEngine engine = isEmpty ? SCRIPT_ENGINE : SCRIPT_ENGINE_MANAGER.getEngineByName(lang); From a7d0f0f0d41ca2de4d7917f6c64a4ae2fd5b5f38 Mon Sep 17 00:00:00 2001 From: TommyLemon Date: Sat, 16 May 2026 23:42:37 +0800 Subject: [PATCH 20/33] =?UTF-8?q?=E5=AE=8C=E5=96=84=E8=84=9A=E6=9C=AC?= =?UTF-8?q?=E5=BC=95=E6=93=8E=E7=9A=84=E4=BD=BF=E7=94=A8=E8=AF=B4=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/apijson/orm/AbstractFunctionParser.java | 4 +++- APIJSONORM/src/main/java/apijson/orm/Operation.java | 7 +++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractFunctionParser.java b/APIJSONORM/src/main/java/apijson/orm/AbstractFunctionParser.java index ac0cc308..7ed7fc4d 100755 --- a/APIJSONORM/src/main/java/apijson/orm/AbstractFunctionParser.java +++ b/APIJSONORM/src/main/java/apijson/orm/AbstractFunctionParser.java @@ -31,7 +31,9 @@ public abstract class AbstractFunctionParser, L /**开启支持远程函数 */ public static boolean ENABLE_REMOTE_FUNCTION = true; - /**开启支持远程函数中的 JavaScript 脚本形式 + /**开启支持远程函数中的 JavaScript/Python/Lua/PHP 等脚本形式。 + * JDK 8~13 可用自带 Nashorn 这个 js 引擎,注意配置 ClassFilter 防脚本注入攻击; + * 其它语言及 JDK 14+ 都必须依赖外部脚本引擎,注意按对应引擎说明方式防脚本注入攻击,最好是沙箱环境。 */ public static boolean ENABLE_SCRIPT_FUNCTION = false; diff --git a/APIJSONORM/src/main/java/apijson/orm/Operation.java b/APIJSONORM/src/main/java/apijson/orm/Operation.java index b69eb9a7..45fcbf47 100755 --- a/APIJSONORM/src/main/java/apijson/orm/Operation.java +++ b/APIJSONORM/src/main/java/apijson/orm/Operation.java @@ -124,9 +124,16 @@ public enum Operation { * 例如 "sex != 0 && sex != 1": "throw new Error('sex 必须在 [0, 1] 内!')" * 自定义代码,当满足条件是执行后面的代码 * + * 还可以指定语言,例如 "python:sex not in(0, 1)": "throw new Error('sex 必须在 [0, 1] 内!')" + * * 还有 * "ELSE": "" * 自定义代码,不处理,和不传一样 + * + * 需要 + * 1.AbstractFunctionParser.ENABLE_SCRIPT_FUNCTION = true 启用 + * 2.JDK 8~13 可用自带 Nashorn 这个 js 引擎,注意配置 ClassFilter 防脚本注入攻击; + * 其它语言及 JDK 14+ 都必须依赖外部脚本引擎,注意按对应引擎说明方式防脚本注入攻击,最好是沙箱环境。 */ IF, From 1344073f5e7c9c6f7590d18ca9b4c597f4db248a Mon Sep 17 00:00:00 2001 From: TommyLemon Date: Sat, 16 May 2026 23:45:14 +0800 Subject: [PATCH 21/33] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=86=85=E7=BD=AE?= =?UTF-8?q?=E8=A1=A8=20model=20=E7=9A=84=E6=9D=83=E9=99=90=EF=BC=8C?= =?UTF-8?q?=E5=88=A0=E9=99=A4=E4=B8=8D=E5=86=8D=E9=9C=80=E8=A6=81=E7=9A=84?= =?UTF-8?q?=20TestRecord?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/apijson/orm/AbstractSQLConfig.java | 2 - .../java/apijson/orm/AbstractVerifier.java | 2 - .../java/apijson/orm/ConfigMethodAccess.java | 29 +++++ .../main/java/apijson/orm/model/Access.java | 6 +- .../java/apijson/orm/model/AllColumn.java | 5 +- .../apijson/orm/model/AllColumnComment.java | 5 +- .../main/java/apijson/orm/model/AllTable.java | 5 +- .../apijson/orm/model/AllTableComment.java | 5 +- .../main/java/apijson/orm/model/Column.java | 5 +- .../main/java/apijson/orm/model/Document.java | 8 +- .../apijson/orm/model/ExtendedProperty.java | 5 +- .../main/java/apijson/orm/model/Function.java | 5 +- .../java/apijson/orm/model/PgAttribute.java | 5 +- .../main/java/apijson/orm/model/PgClass.java | 5 +- .../main/java/apijson/orm/model/Request.java | 5 +- .../main/java/apijson/orm/model/Script.java | 5 +- .../java/apijson/orm/model/SysColumn.java | 5 +- .../main/java/apijson/orm/model/SysTable.java | 5 +- .../main/java/apijson/orm/model/Table.java | 5 +- .../java/apijson/orm/model/TestRecord.java | 107 ------------------ 20 files changed, 94 insertions(+), 130 deletions(-) create mode 100755 APIJSONORM/src/main/java/apijson/orm/ConfigMethodAccess.java delete mode 100644 APIJSONORM/src/main/java/apijson/orm/model/TestRecord.java diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java b/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java index c3532314..05e9f04e 100755 --- a/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java +++ b/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java @@ -142,8 +142,6 @@ public abstract class AbstractSQLConfig, L exte CONFIG_TABLE_LIST.add(Request.class.getSimpleName()); CONFIG_TABLE_LIST.add(Access.class.getSimpleName()); CONFIG_TABLE_LIST.add(Document.class.getSimpleName()); - CONFIG_TABLE_LIST.add(TestRecord.class.getSimpleName()); - DATABASE_LIST = new ArrayList<>(); DATABASE_LIST.add(DATABASE_MYSQL); diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractVerifier.java b/APIJSONORM/src/main/java/apijson/orm/AbstractVerifier.java index 81ccc1ee..81bef3cd 100755 --- a/APIJSONORM/src/main/java/apijson/orm/AbstractVerifier.java +++ b/APIJSONORM/src/main/java/apijson/orm/AbstractVerifier.java @@ -48,7 +48,6 @@ import apijson.orm.model.AllColumn; import apijson.orm.model.AllTableComment; import apijson.orm.model.AllColumnComment; -import apijson.orm.model.TestRecord; import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; @@ -174,7 +173,6 @@ public abstract class AbstractVerifier, L exten SYSTEM_ACCESS_MAP.put(ExtendedProperty.class.getSimpleName(), getAccessMap(ExtendedProperty.class.getAnnotation(MethodAccess.class))); SYSTEM_ACCESS_MAP.put(Document.class.getSimpleName(), getAccessMap(Document.class.getAnnotation(MethodAccess.class))); - SYSTEM_ACCESS_MAP.put(TestRecord.class.getSimpleName(), getAccessMap(TestRecord.class.getAnnotation(MethodAccess.class))); } ACCESS_MAP = new HashMap<>(SYSTEM_ACCESS_MAP); diff --git a/APIJSONORM/src/main/java/apijson/orm/ConfigMethodAccess.java b/APIJSONORM/src/main/java/apijson/orm/ConfigMethodAccess.java new file mode 100755 index 00000000..f8935516 --- /dev/null +++ b/APIJSONORM/src/main/java/apijson/orm/ConfigMethodAccess.java @@ -0,0 +1,29 @@ +/*Copyright (C) 2020 Tencent. All rights reserved. + +This source code is licensed under the Apache License Version 2.0.*/ + + +//package apijson.orm; +// +//import apijson.MethodAccess; +// +//import java.lang.annotation.Documented; +//import java.lang.annotation.Inherited; +//import java.lang.annotation.Retention; +//import java.lang.annotation.Target; +// +//import static apijson.orm.AbstractVerifier.*; +//import static java.lang.annotation.ElementType.TYPE; +//import static java.lang.annotation.RetentionPolicy.RUNTIME; +// +///**配置表的请求方法权限,只允许某些角色通过对应方法访问 +// 不能直接查到 MethodAccess,需要往上递归查找 +// * @author Lemon +// */ +//@Documented +//@Retention(RUNTIME) +//@Target(TYPE) +//@Inherited +//@MethodAccess(GET = {LOGIN, ADMIN}, HEAD = {LOGIN, ADMIN}, POST = {}, PUT = {}, DELETE = {}) +//public @interface ConfigMethodAccess { +//} diff --git a/APIJSONORM/src/main/java/apijson/orm/model/Access.java b/APIJSONORM/src/main/java/apijson/orm/model/Access.java index ab44f866..db934ec9 100644 --- a/APIJSONORM/src/main/java/apijson/orm/model/Access.java +++ b/APIJSONORM/src/main/java/apijson/orm/model/Access.java @@ -7,9 +7,13 @@ import apijson.MethodAccess; +import static apijson.orm.AbstractVerifier.ADMIN; +import static apijson.orm.AbstractVerifier.LOGIN; + /**访问权限 * @author Lemon */ -@MethodAccess(POST = {}, PUT = {}, DELETE = {}) +@MethodAccess(GET = {LOGIN, ADMIN}, HEAD = {LOGIN, ADMIN}, POST = {}, PUT = {}, DELETE = {}) +//@ConfigMethodAccess public class Access { } \ No newline at end of file diff --git a/APIJSONORM/src/main/java/apijson/orm/model/AllColumn.java b/APIJSONORM/src/main/java/apijson/orm/model/AllColumn.java index 02906c6e..f4d93962 100644 --- a/APIJSONORM/src/main/java/apijson/orm/model/AllColumn.java +++ b/APIJSONORM/src/main/java/apijson/orm/model/AllColumn.java @@ -7,10 +7,13 @@ import apijson.MethodAccess; +import static apijson.orm.AbstractVerifier.ADMIN; +import static apijson.orm.AbstractVerifier.LOGIN; + /**SQL Server 在 sys 下的字段(列名) * @author Lemon */ -@MethodAccess(POST = {}, PUT = {}, DELETE = {}) +@MethodAccess(GET = {LOGIN, ADMIN}, HEAD = {LOGIN, ADMIN}, POST = {}, PUT = {}, DELETE = {}) public class AllColumn { public static final String TAG = "AllColumn"; public static final String TABLE_NAME = "ALL_TAB_COLUMNS"; diff --git a/APIJSONORM/src/main/java/apijson/orm/model/AllColumnComment.java b/APIJSONORM/src/main/java/apijson/orm/model/AllColumnComment.java index 81e2c9fe..cf1480f7 100644 --- a/APIJSONORM/src/main/java/apijson/orm/model/AllColumnComment.java +++ b/APIJSONORM/src/main/java/apijson/orm/model/AllColumnComment.java @@ -7,10 +7,13 @@ import apijson.MethodAccess; +import static apijson.orm.AbstractVerifier.ADMIN; +import static apijson.orm.AbstractVerifier.LOGIN; + /**SQL Server 在 sys 下的字段(列名) * @author Lemon */ -@MethodAccess(POST = {}, PUT = {}, DELETE = {}) +@MethodAccess(GET = {LOGIN, ADMIN}, HEAD = {LOGIN, ADMIN}, POST = {}, PUT = {}, DELETE = {}) public class AllColumnComment { public static final String TAG = "AllColumnComment"; public static final String TABLE_NAME = "ALL_COL_COMMENTS"; diff --git a/APIJSONORM/src/main/java/apijson/orm/model/AllTable.java b/APIJSONORM/src/main/java/apijson/orm/model/AllTable.java index 2934ad0b..dcc3268c 100644 --- a/APIJSONORM/src/main/java/apijson/orm/model/AllTable.java +++ b/APIJSONORM/src/main/java/apijson/orm/model/AllTable.java @@ -7,10 +7,13 @@ import apijson.MethodAccess; +import static apijson.orm.AbstractVerifier.ADMIN; +import static apijson.orm.AbstractVerifier.LOGIN; + /**SQL Server 表属性 * @author Lemon */ -@MethodAccess(POST = {}, PUT = {}, DELETE = {}) +@MethodAccess(GET = {LOGIN, ADMIN}, HEAD = {LOGIN, ADMIN}, POST = {}, PUT = {}, DELETE = {}) public class AllTable { public static final String TAG = "AllTable"; public static final String TABLE_NAME = "ALL_TABLES"; diff --git a/APIJSONORM/src/main/java/apijson/orm/model/AllTableComment.java b/APIJSONORM/src/main/java/apijson/orm/model/AllTableComment.java index 49a4dee3..ed61a0b4 100644 --- a/APIJSONORM/src/main/java/apijson/orm/model/AllTableComment.java +++ b/APIJSONORM/src/main/java/apijson/orm/model/AllTableComment.java @@ -7,10 +7,13 @@ import apijson.MethodAccess; +import static apijson.orm.AbstractVerifier.ADMIN; +import static apijson.orm.AbstractVerifier.LOGIN; + /**SQL Server 表属性 * @author Lemon */ -@MethodAccess(POST = {}, PUT = {}, DELETE = {}) +@MethodAccess(GET = {LOGIN, ADMIN}, HEAD = {LOGIN, ADMIN}, POST = {}, PUT = {}, DELETE = {}) public class AllTableComment { public static final String TAG = "AllTableComment"; public static final String TABLE_NAME = "ALL_TAB_COMMENTS"; diff --git a/APIJSONORM/src/main/java/apijson/orm/model/Column.java b/APIJSONORM/src/main/java/apijson/orm/model/Column.java index 573ab7fc..800b60eb 100755 --- a/APIJSONORM/src/main/java/apijson/orm/model/Column.java +++ b/APIJSONORM/src/main/java/apijson/orm/model/Column.java @@ -7,10 +7,13 @@ import apijson.MethodAccess; +import static apijson.orm.AbstractVerifier.ADMIN; +import static apijson.orm.AbstractVerifier.LOGIN; + /**字段(列名)属性 * @author Lemon */ -@MethodAccess(POST = {}, PUT = {}, DELETE = {}) +@MethodAccess(GET = {LOGIN, ADMIN}, HEAD = {LOGIN, ADMIN}, POST = {}, PUT = {}, DELETE = {}) public class Column { public static final String TAG = "Column"; public static final String TABLE_NAME = "columns"; diff --git a/APIJSONORM/src/main/java/apijson/orm/model/Document.java b/APIJSONORM/src/main/java/apijson/orm/model/Document.java index 2e8db19c..1b2bc5d1 100755 --- a/APIJSONORM/src/main/java/apijson/orm/model/Document.java +++ b/APIJSONORM/src/main/java/apijson/orm/model/Document.java @@ -17,10 +17,10 @@ * @author Lemon */ @MethodAccess( - GET = { LOGIN, ADMIN }, - HEAD = { LOGIN, ADMIN }, - PUT = { LOGIN, ADMIN } - ) + GET = { LOGIN, ADMIN }, + HEAD = { LOGIN, ADMIN }, + PUT = { LOGIN, ADMIN } +) public class Document implements Serializable { private static final long serialVersionUID = 1L; diff --git a/APIJSONORM/src/main/java/apijson/orm/model/ExtendedProperty.java b/APIJSONORM/src/main/java/apijson/orm/model/ExtendedProperty.java index 393a7e0d..cc6e04ee 100644 --- a/APIJSONORM/src/main/java/apijson/orm/model/ExtendedProperty.java +++ b/APIJSONORM/src/main/java/apijson/orm/model/ExtendedProperty.java @@ -7,10 +7,13 @@ import apijson.MethodAccess; +import static apijson.orm.AbstractVerifier.ADMIN; +import static apijson.orm.AbstractVerifier.LOGIN; + /**扩展属性,SQL Server 转用 * @author Lemon */ -@MethodAccess(POST = {}, PUT = {}, DELETE = {}) +@MethodAccess(GET = {LOGIN, ADMIN}, HEAD = {LOGIN, ADMIN}, POST = {}, PUT = {}, DELETE = {}) public class ExtendedProperty { public static final String TAG = "ExtendedProperty"; public static final String TABLE_NAME = "extended_properties"; diff --git a/APIJSONORM/src/main/java/apijson/orm/model/Function.java b/APIJSONORM/src/main/java/apijson/orm/model/Function.java index da6c3f53..841e6424 100644 --- a/APIJSONORM/src/main/java/apijson/orm/model/Function.java +++ b/APIJSONORM/src/main/java/apijson/orm/model/Function.java @@ -7,9 +7,12 @@ import apijson.MethodAccess; +import static apijson.orm.AbstractVerifier.ADMIN; +import static apijson.orm.AbstractVerifier.LOGIN; + /**远程函数 * @author Lemon */ -@MethodAccess(POST = {}, PUT = {}, DELETE = {}) +@MethodAccess(GET = {LOGIN, ADMIN}, HEAD = {LOGIN, ADMIN}, POST = {}, PUT = {}, DELETE = {}) public class Function { } \ No newline at end of file diff --git a/APIJSONORM/src/main/java/apijson/orm/model/PgAttribute.java b/APIJSONORM/src/main/java/apijson/orm/model/PgAttribute.java index dbd4b4b6..174b3db0 100644 --- a/APIJSONORM/src/main/java/apijson/orm/model/PgAttribute.java +++ b/APIJSONORM/src/main/java/apijson/orm/model/PgAttribute.java @@ -7,10 +7,13 @@ import apijson.MethodAccess; +import static apijson.orm.AbstractVerifier.ADMIN; +import static apijson.orm.AbstractVerifier.LOGIN; + /**PostgreSQL 字段属性 * @author Lemon */ -@MethodAccess +@MethodAccess(GET = {LOGIN, ADMIN}, HEAD = {LOGIN, ADMIN}, POST = {}, PUT = {}, DELETE = {}) public class PgAttribute { public static final String TAG = "PgAttribute"; public static final String TABLE_NAME = "pg_attribute"; diff --git a/APIJSONORM/src/main/java/apijson/orm/model/PgClass.java b/APIJSONORM/src/main/java/apijson/orm/model/PgClass.java index 199a7ef8..e58feb69 100644 --- a/APIJSONORM/src/main/java/apijson/orm/model/PgClass.java +++ b/APIJSONORM/src/main/java/apijson/orm/model/PgClass.java @@ -7,10 +7,13 @@ import apijson.MethodAccess; +import static apijson.orm.AbstractVerifier.ADMIN; +import static apijson.orm.AbstractVerifier.LOGIN; + /**PostgreSQL 表属性 * @author Lemon */ -@MethodAccess +@MethodAccess(GET = {LOGIN, ADMIN}, HEAD = {LOGIN, ADMIN}, POST = {}, PUT = {}, DELETE = {}) public class PgClass { public static final String TAG = "PgClass"; public static final String TABLE_NAME = "pg_class"; diff --git a/APIJSONORM/src/main/java/apijson/orm/model/Request.java b/APIJSONORM/src/main/java/apijson/orm/model/Request.java index 5d0d0409..46be3d30 100755 --- a/APIJSONORM/src/main/java/apijson/orm/model/Request.java +++ b/APIJSONORM/src/main/java/apijson/orm/model/Request.java @@ -7,9 +7,12 @@ import apijson.MethodAccess; +import static apijson.orm.AbstractVerifier.ADMIN; +import static apijson.orm.AbstractVerifier.LOGIN; + /**请求处理 * @author Lemon */ -@MethodAccess(POST = {}, PUT = {}, DELETE = {}) +@MethodAccess(GET = {LOGIN, ADMIN}, HEAD = {LOGIN, ADMIN}, POST = {}, PUT = {}, DELETE = {}) public class Request { } diff --git a/APIJSONORM/src/main/java/apijson/orm/model/Script.java b/APIJSONORM/src/main/java/apijson/orm/model/Script.java index 53cda432..51205db0 100644 --- a/APIJSONORM/src/main/java/apijson/orm/model/Script.java +++ b/APIJSONORM/src/main/java/apijson/orm/model/Script.java @@ -7,9 +7,12 @@ import apijson.MethodAccess; +import static apijson.orm.AbstractVerifier.ADMIN; +import static apijson.orm.AbstractVerifier.LOGIN; + /**代码脚本 * @author Lemon */ -@MethodAccess(POST = {}, PUT = {}, DELETE = {}) +@MethodAccess(GET = {LOGIN, ADMIN}, HEAD = {LOGIN, ADMIN}, POST = {}, PUT = {}, DELETE = {}) public class Script { } \ No newline at end of file diff --git a/APIJSONORM/src/main/java/apijson/orm/model/SysColumn.java b/APIJSONORM/src/main/java/apijson/orm/model/SysColumn.java index a4d7ca88..534446de 100644 --- a/APIJSONORM/src/main/java/apijson/orm/model/SysColumn.java +++ b/APIJSONORM/src/main/java/apijson/orm/model/SysColumn.java @@ -7,10 +7,13 @@ import apijson.MethodAccess; +import static apijson.orm.AbstractVerifier.ADMIN; +import static apijson.orm.AbstractVerifier.LOGIN; + /**SQL Server 在 sys 下的字段(列名) * @author Lemon */ -@MethodAccess(POST = {}, PUT = {}, DELETE = {}) +@MethodAccess(GET = {LOGIN, ADMIN}, HEAD = {LOGIN, ADMIN}, POST = {}, PUT = {}, DELETE = {}) public class SysColumn { public static final String TAG = "SysColumn"; public static final String TABLE_NAME = "columns"; diff --git a/APIJSONORM/src/main/java/apijson/orm/model/SysTable.java b/APIJSONORM/src/main/java/apijson/orm/model/SysTable.java index bb614231..7b1eb74c 100644 --- a/APIJSONORM/src/main/java/apijson/orm/model/SysTable.java +++ b/APIJSONORM/src/main/java/apijson/orm/model/SysTable.java @@ -7,10 +7,13 @@ import apijson.MethodAccess; +import static apijson.orm.AbstractVerifier.ADMIN; +import static apijson.orm.AbstractVerifier.LOGIN; + /**SQL Server 表属性 * @author Lemon */ -@MethodAccess(POST = {}, PUT = {}, DELETE = {}) +@MethodAccess(GET = {LOGIN, ADMIN}, HEAD = {LOGIN, ADMIN}, POST = {}, PUT = {}, DELETE = {}) public class SysTable { public static final String TAG = "SysTable"; public static final String TABLE_NAME = "tables"; diff --git a/APIJSONORM/src/main/java/apijson/orm/model/Table.java b/APIJSONORM/src/main/java/apijson/orm/model/Table.java index 1ab004cc..45df12fd 100755 --- a/APIJSONORM/src/main/java/apijson/orm/model/Table.java +++ b/APIJSONORM/src/main/java/apijson/orm/model/Table.java @@ -7,10 +7,13 @@ import apijson.MethodAccess; +import static apijson.orm.AbstractVerifier.ADMIN; +import static apijson.orm.AbstractVerifier.LOGIN; + /**表属性 * @author Lemon */ -@MethodAccess(POST = {}, PUT = {}, DELETE = {}) +@MethodAccess(GET = {LOGIN, ADMIN}, HEAD = {LOGIN, ADMIN}, POST = {}, PUT = {}, DELETE = {}) public class Table { public static final String TAG = "Table"; public static final String TABLE_NAME = "tables"; diff --git a/APIJSONORM/src/main/java/apijson/orm/model/TestRecord.java b/APIJSONORM/src/main/java/apijson/orm/model/TestRecord.java deleted file mode 100644 index 32ad98f9..00000000 --- a/APIJSONORM/src/main/java/apijson/orm/model/TestRecord.java +++ /dev/null @@ -1,107 +0,0 @@ -/*Copyright (C) 2020 Tencent. All rights reserved. - -This source code is licensed under the Apache License Version 2.0.*/ - - -package apijson.orm.model; - -import static apijson.orm.AbstractVerifier.ADMIN; -import static apijson.orm.AbstractVerifier.LOGIN; - -import java.io.Serializable; -import java.sql.Timestamp; - -import apijson.MethodAccess; - -/**测试结果。5.0.0 之后可能改名为 Test - * @author Lemon - */ -@MethodAccess(GET = { LOGIN, ADMIN }, HEAD = { LOGIN, ADMIN }) -public class TestRecord implements Serializable { - private static final long serialVersionUID = 1L; - - private Long id; //唯一标识 - private Long userId; //用户id - private Long documentId; //测试用例文档id - private Timestamp date; //创建日期 - private String compare; //对比结果 - private String response; //接口返回结果JSON 用json格式会导致强制排序,而请求中引用赋值只能引用上面的字段,必须有序。 - private String standard; //response 的校验标准,是一个 JSON 格式的 AST ,描述了正确 Response 的结构、里面的字段名称、类型、长度、取值范围 等属性。 - - - public TestRecord() { - super(); - } - public TestRecord(long id) { - this(); - setId(id); - } - - - - - public Long getId() { - return id; - } - - public TestRecord setId(Long id) { - this.id = id; - return this; - } - - public Long getUserId() { - return userId; - } - - public TestRecord setUserId(Long userId) { - this.userId = userId; - return this; - } - - public Long getDocumentId() { - return documentId; - } - - public TestRecord setDocumentId(Long documentId) { - this.documentId = documentId; - return this; - } - - public Timestamp getDate() { - return date; - } - - public TestRecord setDate(Timestamp date) { - this.date = date; - return this; - } - - public String getCompare() { - return compare; - } - - public TestRecord setCompare(String compare) { - this.compare = compare; - return this; - } - - public String getResponse() { - return response; - } - - public TestRecord setResponse(String response) { - this.response = response; - return this; - } - - public String getStandard() { - return standard; - } - - public TestRecord setStandard(String standard) { - this.standard = standard; - return this; - } - - - } \ No newline at end of file From 6b7c4d586341d70bd0416a0730e7db16784274ae Mon Sep 17 00:00:00 2001 From: TommyLemon Date: Sat, 16 May 2026 23:49:27 +0800 Subject: [PATCH 22/33] =?UTF-8?q?=E5=8D=87=E7=BA=A7=E7=89=88=E6=9C=AC?= =?UTF-8?q?=E4=B8=BA=208.1.8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- APIJSONORM/pom.xml | 2 +- APIJSONORM/src/main/java/apijson/Log.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/APIJSONORM/pom.xml b/APIJSONORM/pom.xml index fb050e32..7a35eb01 100644 --- a/APIJSONORM/pom.xml +++ b/APIJSONORM/pom.xml @@ -5,7 +5,7 @@ com.github.Tencent APIJSON - 8.1.7 + 8.1.8 jar APIJSONORM diff --git a/APIJSONORM/src/main/java/apijson/Log.java b/APIJSONORM/src/main/java/apijson/Log.java index e4bd7ba7..f00e495a 100755 --- a/APIJSONORM/src/main/java/apijson/Log.java +++ b/APIJSONORM/src/main/java/apijson/Log.java @@ -12,6 +12,7 @@ */ public class Log { public static boolean DEBUG = false; + public static final String VERSION = "8.1.8"; public static final String LEVEL_VERBOSE = "VERBOSE"; public static final String LEVEL_INFO = "INFO"; @@ -21,7 +22,6 @@ public class Log { public static String LEVEL = LEVEL_WARN; - public static final String VERSION = "8.1.7"; public static final String KEY_SYSTEM_INFO_DIVIDER = "\n---|-----APIJSON SYSTEM INFO-----|---\n"; public static final String OS_NAME; From e321a94fc2cc4b85cdcb8cd3c6c0bf0ea69c811d Mon Sep 17 00:00:00 2001 From: TommyLemon <1184482681@qq.com> Date: Sun, 17 May 2026 01:00:53 +0800 Subject: [PATCH 23/33] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E6=96=87=E7=AB=A0=20?= =?UTF-8?q?=E7=9C=81=E5=BF=83=E7=9C=81=E5=8A=9B=E7=9A=84=E5=90=8E=E7=AB=AF?= =?UTF-8?q?=E7=A5=9E=E5=99=A8=E2=80=94=E2=80=94APIJSON.NET?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 感谢 妙堂传奇 的贡献,点赞、收藏、转发 支持下热心的作者吧 ^_^ https://mp.weixin.qq.com/s/8-E-a18NttdA0AAqasE0AQ --- README-Chinese.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README-Chinese.md b/README-Chinese.md index 8fd9e98c..f866e0bc 100644 --- a/README-Chinese.md +++ b/README-Chinese.md @@ -539,6 +539,8 @@ Issue/问卷 一般解答顺序:贡献者 > 帮助他人的用户 > 提供任 [3分钟掌握APIJSON搜索黑科技:从模糊匹配到智能检索](https://blog.csdn.net/gitblog_00009/article/details/152403741) +[省心省力的后端神器——APIJSON.NET](https://mp.weixin.qq.com/s/8-E-a18NttdA0AAqasE0AQ) + ### 生态项目 [APIJSON-Demo](https://github.com/APIJSON/APIJSON-Demo) APIJSON 各种语言、各种框架 的 使用示例项目、上手文档、测试数据 SQL 文件 等 From 441e1fa1716d250785f0f1b34f2b9c8d090d6c8f Mon Sep 17 00:00:00 2001 From: Nguyen Van Nam Date: Sun, 17 May 2026 03:49:38 +0700 Subject: [PATCH 24/33] fix(security): unsandboxed jsr223 script execution enables arbitr MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit JSR223ScriptExecutor.load() compiles arbitrary script strings via Compilable.compile() and execute() runs them via eval() with no ClassFilter, sandbox, or restricted ScriptContext. The bindings expose `_meta`, `args`, and `extParam`, but Nashorn/JS engines by default give scripts full access to Java reflection (e.g., Java.type('java.lang.Runtime').getRuntime().exec(...)). Comments in Operation.java explicitly warn 'JDK 8~13 可用自带 Nashorn 这个 js 引擎,注意配置 ClassFilter 防脚本注入攻击', but no ClassFilter is configured here. If script content is sourced from a database row, request payload, or any user-influenced channel (which the IF/CODE Operation suggests), this becomes RCE. Affected files: JSR223ScriptExecutor.java Signed-off-by: Nguyen Van Nam --- .../orm/script/JSR223ScriptExecutor.java | 27 +++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/APIJSONORM/src/main/java/apijson/orm/script/JSR223ScriptExecutor.java b/APIJSONORM/src/main/java/apijson/orm/script/JSR223ScriptExecutor.java index 9c2c9baf..7e08a945 100644 --- a/APIJSONORM/src/main/java/apijson/orm/script/JSR223ScriptExecutor.java +++ b/APIJSONORM/src/main/java/apijson/orm/script/JSR223ScriptExecutor.java @@ -27,11 +27,34 @@ public abstract class JSR223ScriptExecutor, L e @Override public ScriptExecutor init() { - ScriptEngineManager scriptEngineManager = new ScriptEngineManager(); - scriptEngine = scriptEngineManager.getEngineByName(scriptEngineName()); + scriptEngine = createScriptEngine(); return this; } + protected ScriptEngine createScriptEngine() { + String name = scriptEngineName(); + if ("nashorn".equalsIgnoreCase(name) || "javascript".equalsIgnoreCase(name) + || "js".equalsIgnoreCase(name) || "ecmascript".equalsIgnoreCase(name)) { + try { + Class factoryClass = Class.forName("jdk.nashorn.api.scripting.NashornScriptEngineFactory"); + Class filterClass = Class.forName("jdk.nashorn.api.scripting.ClassFilter"); + Object filter = java.lang.reflect.Proxy.newProxyInstance( + filterClass.getClassLoader(), + new Class[]{filterClass}, + (proxy, method, methodArgs) -> isClassExposureAllowed((String) methodArgs[0])); + Object factory = factoryClass.getDeclaredConstructor().newInstance(); + return (ScriptEngine) factoryClass.getMethod("getScriptEngine", filterClass).invoke(factory, filter); + } catch (Throwable e) { + Log.e(TAG, "create sandboxed Nashorn engine failed, falling back: " + e); + } + } + return new ScriptEngineManager().getEngineByName(name); + } + + protected boolean isClassExposureAllowed(String className) { + return false; + } + protected abstract String scriptEngineName(); protected abstract Object extendParameter(AbstractFunctionParser parser, Map currentObject, String methodName, Object[] args); From bf4ef186c62c484d0d134dc238ed6194f51ff636 Mon Sep 17 00:00:00 2001 From: Nguyen Van Nam Date: Sun, 17 May 2026 03:52:07 +0700 Subject: [PATCH 25/33] =?UTF-8?q?fix:=20resolve=20#853=20=E2=80=94=20[Feat?= =?UTF-8?q?ure]=208.x=E7=89=88=E6=9C=AC=E6=B2=A1=E6=9C=89Demo=E5=90=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #853 Signed-off-by: Nguyen Van Nam --- APIJSONORM/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/APIJSONORM/README.md b/APIJSONORM/README.md index 0cb431e2..8aa82f2a 100644 --- a/APIJSONORM/README.md +++ b/APIJSONORM/README.md @@ -21,7 +21,7 @@ Tencent [APIJSON](https://github.com/Tencent/APIJSON) ORM library for remote dep com.github.Tencent APIJSON - LATEST + 8.0.0 ``` @@ -45,7 +45,7 @@ Tencent [APIJSON](https://github.com/Tencent/APIJSON) ORM library for remote dep #### 2. Add the APIJSON dependency in one of your modules(such as `app`) ```gradle dependencies { - implementation 'com.github.Tencent:APIJSON:latest' + implementation 'com.github.Tencent:APIJSON:8.0.0' } ``` From a009c85443d26f4300cc788e567ae2e0ac0d8e95 Mon Sep 17 00:00:00 2001 From: TommyLemon <1184482681@qq.com> Date: Sun, 24 May 2026 10:32:56 +0800 Subject: [PATCH 26/33] readme: replace version to latest, thx to Nam0101 #859 https://github.com/Tencent/APIJSON/pull/859 --- APIJSONORM/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/APIJSONORM/README.md b/APIJSONORM/README.md index 8aa82f2a..745733b4 100644 --- a/APIJSONORM/README.md +++ b/APIJSONORM/README.md @@ -21,7 +21,7 @@ Tencent [APIJSON](https://github.com/Tencent/APIJSON) ORM library for remote dep com.github.Tencent APIJSON - 8.0.0 + 8.1.8 ``` @@ -45,7 +45,7 @@ Tencent [APIJSON](https://github.com/Tencent/APIJSON) ORM library for remote dep #### 2. Add the APIJSON dependency in one of your modules(such as `app`) ```gradle dependencies { - implementation 'com.github.Tencent:APIJSON:8.0.0' + implementation 'com.github.Tencent:APIJSON:8.1.8' } ``` From 8f2c951a317399d46a9876690ac4e682c73fa319 Mon Sep 17 00:00:00 2001 From: TommyLemon <1184482681@qq.com> Date: Mon, 8 Jun 2026 00:12:47 +0800 Subject: [PATCH 27/33] Update README-Chinese.md --- README-Chinese.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README-Chinese.md b/README-Chinese.md index f866e0bc..9737564f 100644 --- a/README-Chinese.md +++ b/README-Chinese.md @@ -650,7 +650,7 @@ Issue/问卷 一般解答顺序:贡献者 > 帮助他人的用户 > 提供任 [xyerp](https://gitee.com/yinjg1997/xyerp) 基于ApiJson的低代码ERP -[quick-boot](https://github.com/csx-bill/quick-boot) 基于 Spring Cloud 2022、Spring Boot 3、AMIS 和 APIJSON 的低代码系统。 +[quick-boot](https://github.com/csx-bill/quick-boot/tree/master) 基于 Spring Cloud 2022、Spring Boot 3、AMIS 和 APIJSON 的低代码系统。 [apijson-query-spring-boot-starter](https://gitee.com/mingbaobaba/apijson-query-spring-boot-starter) 一个快速构建 APIJSON 查询条件的插件 From 5789d667e4c36edb2ca124d793fa8a595c2a1f81 Mon Sep 17 00:00:00 2001 From: Zhengcy05 <1825478405@qq.com> Date: Thu, 11 Jun 2026 17:25:50 +0800 Subject: [PATCH 28/33] fix: fix global @explain not effective --- APIJSONORM/src/main/java/apijson/orm/AbstractObjectParser.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractObjectParser.java b/APIJSONORM/src/main/java/apijson/orm/AbstractObjectParser.java index c4f7c5ff..5fd00c17 100755 --- a/APIJSONORM/src/main/java/apijson/orm/AbstractObjectParser.java +++ b/APIJSONORM/src/main/java/apijson/orm/AbstractObjectParser.java @@ -375,7 +375,7 @@ else if (_method == PUT && value instanceof List && (whereList == null || whe if (isSubquery == false) { // 解决 SQL 语法报错,子查询不能 EXPLAIN Boolean exp = parser.getGlobalExplain(); - if (sch != null) { + if (exp != null) { sqlRequest.putIfAbsent(JSONMap.KEY_EXPLAIN, exp); } From 0f0231dd90bf2d0c093282c736e1594d45ff6106 Mon Sep 17 00:00:00 2001 From: TommyLemon <1184482681@qq.com> Date: Tue, 23 Jun 2026 21:56:05 +0800 Subject: [PATCH 29/33] Add Ecosystem for README.md: https://github.com/Tencent/APIJSON#ecosystem --- README.md | 135 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 133 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f6c637fd..cff65b99 100644 --- a/README.md +++ b/README.md @@ -141,7 +141,7 @@ You're gonna leave 'em all in awe, awe, awe.
**Tired with endless arguments about HTTP API dev or use?**
**Use APIJSON-the ORM for providing infinity codeless CRUD APIs that fit almost all your needs.**
-**Unfold the Power(In Your Soul) with ⭐Star & Clone.** +**Unfold the Power(In Your Soul) with ⭐ Star & Clone.** ### APIJSON Show #### Postman test APIJSON @@ -215,7 +215,7 @@ Please have a look at the [open issues](https://github.com/Tencent/APIJSON/issue Fork the project and send a pull request.
-Please also ⭐Star the project! +### Please also ⭐ Star(on the top right) this project!
##

5. Releases

@@ -322,5 +322,136 @@ a lot of employees from big famous companies(Tencent, Huawei, Microsoft, Zoom, e image image +### Ecosystem +[APIJSON-Demo](https://github.com/APIJSON/APIJSON-Demo) Demo projects with document and SQL files for APIJSON with different programming languages and different frameworks + +[apijson-orm](https://github.com/APIJSON/apijson-orm) APIJSON ORM library, Maven, Gradle, etc can be used for dependencies + +[apijson-framework](https://github.com/APIJSON/apijson-framework) APIJSON Server Framework for configuring access of roles and validation of arguments in database tables, then using APIJSON easier + +[apijson-router](https://github.com/APIJSON/apijson-router) A router plugin for APIJSON, expose undercontrolled RESTful-like HTTP API to public network, transfer to APIJSON request and execute + +[apijson-column](https://github.com/APIJSON/apijson-column) A column plugin for Tencent APIJSON, supports Column Inverse and Column Mapping + +[apijson-jackson](https://github.com/APIJSON/apijson-jackson) A jackson plugin for APIJSON + +[apijson-fastjson2](https://github.com/APIJSON/apijson-fastjson2) A fastjson2 plugin for APIJSON + +[apijson-gson](https://github.com/APIJSON/apijson-gson) A gson plugin for APIJSON + +[apijson-milvus](https://github.com/APIJSON/apijson-milvus) An APIJSON plugin for Milvus - An AI vector database + +[apijson-influxdb](https://github.com/APIJSON/apijson-influxdb) An APIJSON plugin for InfluxDB - An IoT time-series database + +[apijson-mongodb](https://github.com/APIJSON/apijson-mongodb) An APIJSON plugin for MongoDB - A NoSQL database + +[apijson-cassandra](https://github.com/APIJSON/apijson-cassandra) An APIJSON plugin for Cassandra - A NoSQL database + +[APIAuto](https://github.com/TommyLemon/APIAuto) ☔ The most advanced tool for HTTP API. Machine learning no-code testing and AI assistant, generating codes and static analysis, generating comments and floating hints. Used by Tencent, SHEIN, TRANSSION, etc + +[CVAuto](https://github.com/TommyLemon/CVAuto) 👁 No-code, zero-annotation CV(Computer Vision) AI automated testing tool 🚀 Eliminates the need for extensive manual tasks such as drawing bounding boxes and labeling for image recognition algorithms + +[UnitAuto](https://github.com/TommyLemon/UnitAuto) ☀️ The most advanced unit testing way powered by machine learning. Coding-free, comprehensive and automatic testing for methods/functions. Used by Tencent, Kwai, a Fortune 500 company, etc + +[SQLAuto](https://github.com/TommyLemon/SQLAuto) 🔍 A smart SQL testing automation tool for databases, supports any CRUD, any template variables, generating argument combinations, generating lots of data rows + +[UIGO](https://github.com/TommyLemon/UIGO) 📱 Coding-free, fast, accurate and stable UI replayer 🚀 Incredible ±3px auto locating and ±2ms auto waiting. Used by Tencent, invited by WeChat team to share + +[APIJSONdocs](https://github.com/ruoranw/APIJSONdocs) APIJSON English documentation, provided a website to view + +[apijson-doc](https://github.com/vincentCheng/apijson-doc) APIJSON Chinese documentation, provided a website to view + +[apijson.org](https://github.com/APIJSON/apijson.org) APIJSON official website + +[APIJSON.NET](https://github.com/liaozb/APIJSON.NET) APIJSON for C#, supports CRUD for MySQL, PostgreSQL, SQL Server, Oracle, SQLite + +[apijson-go](https://github.com/glennliao/apijson-go) APIJSON for Go, based on Go(>=1.18) + GoFrame2, support CRUD + +[apijson-go](https://gitee.com/tiangao/apijson-go) APIJSON for Go, support CRUD, can directly run in Docker + +[apijson-hyperf](https://github.com/kvnZero/hyperf-APIJSON.git) APIJSON for PHP, based on Hyperf, supports MySQL + +[APIJSON-php](https://github.com/xianglong111/APIJSON-php) APIJSON for PHP, based on ThinkPHP,supports MySQL, PostgreSQL, SQL Server, Oracle, etc + +[apijson-php](https://github.com/qq547057827/apijson-php) APIJSON for PHP, based on ThinkPHP,supports MySQL, PostgreSQL, SQL Server, Oracle, etc + +[apijson-node](https://github.com/kevinaskin/apijson-node) APIJSON for Node.js, developed by a ByteDance engineer, provides demos for NestJS and Typeorm, as well as backend management + +[nestjs-apijson](https://github.com/yangzhouQS/nestjs-apijson) APIJSON for NestJS, supports CRUD, Joins for MySQL, PostgreSQL, SQLite (AI assisted) + +[uliweb-apijson](https://github.com/zhangchunlin/uliweb-apijson) APIJSON for Python, supports CRUD for MySQL, PostgreSQL, SQL Server, Oracle, SQLite, etc + +[apijson-rust](https://github.com/APIJSON/apijson-rust) APIJSON for Rust, supports CRUD for MySQL and PostgreSQL (AI assisted) + +[APIJSONParser](https://github.com/Zerounary/APIJSONParser) An APIJSON Parser, dynamically parses JSON to SQL + +[FfApiJson](https://gitee.com/own_3_0/ff-api-json) An APIJSON Parser, parses JSON to SQL, supports multiple data sources + +[APIJSON-ToDo-Demo](https://github.com/jerrylususu/apijson_todo_demo) A simple TODO demo for APIJSON with customized authorization and authentication + +[apijson-learn](https://github.com/rainboy-learn/apijson-learn) APIJSON study note and analysis for source code + +[apijson-practice](https://github.com/vcoolwind/apijson-practice) A library for APIJSON parameter validation annotations and related demos, open-sourced by a BAT expert + +[apijson-db2](https://github.com/andream7/apijson-db2) Demo of APIJSON + IBM DB2 database, open-sourced by a Microsoft engineer + +[APIJSONDemo](https://github.com/qiujunlin/APIJSONDemo) Demo of APIJSON + ClickHouse database, open-sourced by a ByteDance engineer + +[APIJSONDemo_ClickHouse](https://github.com/chenyanlann/APIJSONDemo_ClickHouse) Demo for APIJSON + SpringBoot + ClickHouse + +[APIJSONBoot_Hive](https://github.com/chenyanlann/APIJSONBoot_Hive) Demo for APIJSON + SpringBoot + Hive + +[apijson-sample](https://gitee.com/greyzeng/apijson-sample) Simple demo and tutorial for using APIJSON + +[apijson-examples](https://gitee.com/drone/apijson-examples) Demo for APIJSON with frontend web page, backend server and management system + +[apijson-ruoyi](https://github.com/daodol/apijson-ruoyi) APIJSON + RuoYi, provides online maintenance for database configuration, etc + +[light4j](https://github.com/xlongwei/light4j) Demo for APIJSON + Redis + light-4j - a microservices framework + +[SpringServer1.2-APIJSON](https://github.com/Airforce-1/SpringServer1.2-APIJSON) The smart Party building server provides interfaces for uploading and downloading files + +[apijson_template](https://github.com/abliger/apijson_template) APIJSON Java template, using Gradle to manage dependencie and building apps + +[api-json-demo](https://gitee.com/hxdwd/api-json-demo) Demo for APIJSON to replace traditional ORM, compated Oracle transactions + +[ApiJsonByJFinal](https://gitee.com/zhiyuexin/ApiJsonByJFinal) Demo for APIJSON + JFinal - a popular web framework + +[bookmark](https://github.com/glennliao/bookmark) Online bookmark using goframe + apijson-go + vue3 + antd vue 4 + +[apijson-go-demo](https://github.com/APIJSON/apijson-go-demo) Demo for apijson-go + +[apijson-go-ui](https://github.com/glennliao/apijson-go-ui) apijson-go UI config, supports access control, request rule configuration, etc + +[apijson-builder](https://github.com/pengxianggui/apijson-builder) A JavaScript client library providing RESTful-like functions for APIJSON + +[AbsGrade](https://github.com/APIJSON/AbsGrade) List cascading algorithm supports single-level comments in WeChat Moments, double-level comments in QQ Space, and multi-level (unlimited-level) folders in Baidu Cloud + +[APIJSON-Android-RxJava](https://github.com/TommyLemon/APIJSON-Android-RxJava) Practical project mimicking WeChat Moments updates, based on ZBLibrary(UI) + APIJSON(HTTP) + RxJava(Data) + +[Android-ZBLibrary](https://github.com/TommyLemon/Android-ZBLibrary) 🔥 An Android MVP Framework with many demos, detailed documents, simple usages and strict codes + +[apijson-dynamic-datasource](https://github.com/wb04307201/apijson-dynamic-datasource) Based on APIJSON, this demo demonstrates dynamic data source switching and batch operations on the same data source to ensure transaction consistency + +[xyerp](https://gitee.com/yinjg1997/xyerp) Low-code ERP based on APIJSON + +[quick-boot](https://github.com/csx-bill/quick-boot/tree/master) Low-code system based on Spring Cloud 2022 + Spring Boot 3 + AMIS + APIJSON + +[apijson-query-spring-boot-starter](https://gitee.com/mingbaobaba/apijson-query-spring-boot-starter) A plugin for quickly building APIJSON query conditions + +[apijson-builder](https://github.com/yeli19950109/apijson-builder) A simplified TypeScript wrapper for APIJSON, easier to remember than directly constructing query JSON + +[lanmuc](https://gitee.com/element-admin/lanmuc) A platform for producing low-code backend APIs, compatible with both configuration-based and code-based APIs, enabling rapid API production and project deployment + +[review_plan](https://gitee.com/PPXcodeTry/review_plan) Review Reminder Web Version (Java Technology Practice Project) + +[apijson-nutz](https://github.com/vincent109/apijson-nutz) Demo for APIJSON + Nutz + NutzBoot + +[apijson-spring-boot](https://gitee.com/yunjiao-source/apijson-spring-boot) Springboot3 for APIJSON, using YAML to simplify configuration + +[APIJSONServer](https://github.com/cyber2jie/APIJSONServer) Data server based on APIJSON + +Thank you to all the enthusiastic authors for the contributions~
+### Please give them a ⭐ Star(on the top right) to support their hard works!
From 9606842f0feba9e5b031ac383280e101bd3a00e1 Mon Sep 17 00:00:00 2001 From: TommyLemon <1184482681@qq.com> Date: Tue, 23 Jun 2026 22:06:17 +0800 Subject: [PATCH 30/33] =?UTF-8?q?=E7=94=9F=E6=80=81=E6=96=B0=E5=A2=9E=20ne?= =?UTF-8?q?stjs-apijson=20-=20=E6=94=AF=E6=8C=81=20CRUD=E3=80=81JOIN?= =?UTF-8?q?=E3=80=81=E5=90=84=E7=A7=8D=E6=9D=A1=E4=BB=B6=20(AI=20=E8=BE=85?= =?UTF-8?q?=E5=8A=A9)=E3=80=81bookmark=20-=20goframe=20+=20apijson-go=20+?= =?UTF-8?q?=20vue3=20+=20antd=20vue=204=20=E7=9A=84=E5=9C=A8=E7=BA=BF?= =?UTF-8?q?=E4=B9=A6=E7=AD=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 创作不易,打开下方链接右上角点亮 ⭐️ Star 收藏/支持 下热心的作者们吧 ^_^ 1.nestjs-apijson - APIJSON for NestJS,支持 CRUD、JOIN、各种条件 (AI 辅助) https://github.com/yangzhouQS/nestjs-apijson 2.bookmark - goframe + apijson-go + vue3 + antd vue 4 的在线书签 https://github.com/glennliao/bookmark --- README-Chinese.md | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/README-Chinese.md b/README-Chinese.md index 9737564f..ad77e388 100644 --- a/README-Chinese.md +++ b/README-Chinese.md @@ -413,7 +413,7 @@ https://github.com/Tencent/APIJSON/blob/master/Roadmap.md [OceanBase](https://www.oceanbase.com/docs/oceanbase/V2.2.50/ss-sr-select_daur3l), [Spark](https://spark.apache.org/docs/3.3.0/sql-ref-syntax-qry-select.html)(可用 Hive 对接), [Phoenix](http://phoenix.apache.org/language/index.html#select)(延伸支持 HBase) ### 我要赞赏 -创作不易,坚持更难,右上角点 ⭐Star 来支持/收藏下吧,谢谢 ^_^
+创作不易,坚持更难,右上角点亮 ⭐ Star 来收藏/支持下吧,谢谢 ^_^
https://github.com/Tencent/APIJSON
@@ -596,9 +596,11 @@ Issue/问卷 一般解答顺序:贡献者 > 帮助他人的用户 > 提供任 [apijson-node](https://github.com/kevinaskin/apijson-node) 字节跳动工程师开源的 Node.ts 版 APIJSON,提供 nestjs 和 typeorm 的 Demo 及后台管理 +[nestjs-apijson](https://github.com/yangzhouQS/nestjs-apijson) APIJSON NestJS 版,支持 CRUD、JOIN、各种条件,适配 MySQL, PostgreSQL, SQLite (AI 辅助) + [uliweb-apijson](https://github.com/zhangchunlin/uliweb-apijson) Python 版 APIJSON,支持 MySQL, PostgreSQL, SQL Server, Oracle, SQLite 等 -[apijson-rust](https://github.com/APIJSON/apijson-rust) APIJSON 的 Rust 版,一个优雅、高性能的 Rust 多数据源管理系统,支持 MySQL 和 PostgreSQL +[apijson-rust](https://github.com/APIJSON/apijson-rust) APIJSON 的 Rust 版,一个优雅、高性能的 Rust 多数据源管理系统,支持 MySQL 和 PostgreSQL (AI 辅助) [APIJSONParser](https://github.com/Zerounary/APIJSONParser) 第三方 APIJSON 解析器,将 JSON 动态解析成 SQL @@ -634,7 +636,9 @@ Issue/问卷 一般解答顺序:贡献者 > 帮助他人的用户 > 提供任 [ApiJsonByJFinal](https://gitee.com/zhiyuexin/ApiJsonByJFinal) 整合 APIJSON 和 JFinal 的 Demo -[apijson-go-demo](https://github.com/glennliao/apijson-go-demo) apijson-go demos,提供 3 个从简单到复杂的不同场景 Demo +[bookmark](https://github.com/glennliao/bookmark) goframe + apijson-go + vue3 + antd vue 4 的在线书签 + +[apijson-go-demo](https://github.com/APIJSON/apijson-go-demo) apijson-go demos,提供 3 个从简单到复杂的不同场景 Demo [apijson-builder](https://github.com/pengxianggui/apijson-builder) 一个方便为 APIJSON 构建 RESTful 请求的 JavaScript 库 @@ -666,7 +670,7 @@ Issue/问卷 一般解答顺序:贡献者 > 帮助他人的用户 > 提供任 [APIJSONServer](https://github.com/cyber2jie/APIJSONServer) 基于APIJSON实现的数据服务端 -感谢热心的作者们的贡献,点 ⭐Star 支持下他们吧~ +感谢热心的作者们的贡献,点亮 ⭐ Star 收藏/支持下他们吧~ ### 腾讯犀牛鸟开源人才培养计划 From 14551cdc6b28f2954e03af91bcfa9f2416ce3c39 Mon Sep 17 00:00:00 2001 From: TommyLemon <1184482681@qq.com> Date: Mon, 29 Jun 2026 00:19:59 +0800 Subject: [PATCH 31/33] AI: Create context7.json for LLM AI Skills https://context7.com/tencent/apijson --- context7.json | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 context7.json diff --git a/context7.json b/context7.json new file mode 100644 index 00000000..7059d93f --- /dev/null +++ b/context7.json @@ -0,0 +1,4 @@ +{ + "url": "https://context7.com/tencent/apijson", + "public_key": "pk_hqcWKqm5UmWzQouumDz3F" +} From 76cb2c46cce66fd03ca351d4e07470c499cdde85 Mon Sep 17 00:00:00 2001 From: TommyLemon <1184482681@qq.com> Date: Mon, 29 Jun 2026 01:04:12 +0800 Subject: [PATCH 32/33] =?UTF-8?q?doc:=20add=20LLM=20AI=20Skills,=20MCP,=20?= =?UTF-8?q?A2A=20/=20=E6=96=87=E6=A1=A3=EF=BC=9A=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E5=A4=A7=E6=A8=A1=E5=9E=8B=20AI=20Skills,=20MCP,=20A2A=20?= =?UTF-8?q?=E5=85=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 感谢 Upstash Context7 和 YRO.ai https://github.com/Tencent/APIJSON/issues/864 https://github.com/Tencent/APIJSON/issues/861 --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index cff65b99..0bcb1841 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,9 @@ This source code is licensed under the Apache License Version 2.0
 Video   Test  Ask AI + Skills + MCP + A2A

@@ -75,7 +78,7 @@ This source code is licensed under the Apache License Version 2.0

- +

From 5ac449c03b8bde5c694445ec019f2d43d0acbdbb Mon Sep 17 00:00:00 2001 From: TommyLemon <1184482681@qq.com> Date: Mon, 29 Jun 2026 01:06:02 +0800 Subject: [PATCH 33/33] =?UTF-8?q?doc:=20add=20LLM=20AI=20Skills,=20MCP,=20?= =?UTF-8?q?A2A=20/=20=E6=96=87=E6=A1=A3=EF=BC=9A=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E5=A4=A7=E6=A8=A1=E5=9E=8B=20AI=20Skills,=20MCP,=20A2A=20?= =?UTF-8?q?=E5=85=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Thanks to Upstash Context7 and YRO.ai ~ 感谢 Upstash Context7 和 YRO.ai ~ https://github.com/Tencent/APIJSON/issues/864 https://github.com/Tencent/APIJSON/issues/861 --- README-Chinese.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README-Chinese.md b/README-Chinese.md index ad77e388..c13f82e9 100644 --- a/README-Chinese.md +++ b/README-Chinese.md @@ -14,6 +14,9 @@ This source code is licensed under the Apache License Version 2.0
视频教程 测试用例 AI 问答 + Skills + MCP + A2A