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/15] 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/15] 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/15] 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/15] 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/15] =?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/15] =?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/15] =?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/15] =?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/15] =?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/15] =?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/15] =?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/15] =?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/15] 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/15] =?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/15] =?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)