Tencent / APIJSON

🏆 实时 零代码、全功能、强安全 ORM 库 🚀 后端接口和文档零代码,前端(客户端) 定制返回 JSON 的数据和结构 🏆 Real-Time coding-free, powerful and secure ORM 🚀 providing APIs and Docs without coding by Backend, and the returned JSON of API can be customized by Frontend(Client) users
http://apijson.cn
Other
17.1k stars 2.14k forks source link

GETS 返回错误内容 #115

Closed westerly-lzh closed 2 years ago

westerly-lzh commented 4 years ago

环境信息

按照文档描述,GETS和GET的传入参数区别仅仅是GETS多了一个TAG,

如下GET可以得到正确的返回内容: { "[]": { "User": {} } }

返回:

{ "msg": "success", "[]": [ { "User": { "modifyDate": "2019-11-20", "id": "123456", "createDate": "2019-11-20", "status": "OK" } }, { "User": { "modifyDate": "2019-12-20", "id": "456789", "createDate": "2019-11-20", "status": "Error" } } ], "code": 200, "time:start|duration|end": "1575794122799|17|1575794122816", "depth:count|max": "3|5", "sql:generate|cache|execute|maxExecute": "3|2|1|200" }

如下GETS的传参和返回结果: { "[]":{ "User":{} }, "tag":"User" }

返回

{ "[]": { "User": {} }, "code": 406, "msg": "GETS请求,请在 内传 User:{} !" }

下面是后台的错误日志: AbstractSQLExecutor.INFO: >>> select putCache('SELECT "structure" FROM "public"."sys_request" WHERE ( ("method" = 'GETS') AND ("tag" = 'User') ) ORDER BY "version" DESC LIMIT 1 OFFSET 0', resultList); resultList.size() = 1 Structure.INFO: parseRequest method = GETS; name = ; target = {"User":{}} request = {"[]":{"User":{}}} java.lang.IllegalArgumentException: GETS请求,请在 内传 User:{} ! at zuo.biao.apijson.server.Structure$1.onParseJSONObject(Structure.java:116) at zuo.biao.apijson.server.Structure.parse(Structure.java:303) at zuo.biao.apijson.server.Structure.parseRequest(Structure.java:109) at zuo.biao.apijson.server.AbstractParser.parseCorrectRequest(AbstractParser.java:466) at zuo.biao.apijson.server.AbstractParser.parseCorrectRequest(AbstractParser.java:622) at zuo.biao.apijson.server.AbstractParser.onVerifyContent(AbstractParser.java:423) at zuo.biao.apijson.server.AbstractParser.parseResponse(AbstractParser.java:332) at zuo.biao.apijson.server.AbstractParser.parseResponse(AbstractParser.java:306) at zuo.biao.apijson.server.AbstractParser.parse(AbstractParser.java:278) at com.dathinking.gancao.controller.APIController.gets(APIController.java:72) at jdk.internal.reflect.GeneratedMethodAccessor2.invoke(Unknown Source) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:567) at com.jfinal.aop.Invocation.invoke(Invocation.java:97) at com.jfinal.ext.interceptor.POST.intercept(POST.java:30) at com.jfinal.aop.Invocation.invoke(Invocation.java:91) at com.dathinking.gancao.jfinal.interceptor.CrosInterceptor.intercept(CrosInterceptor.java:12) at com.jfinal.aop.Invocation.invoke(Invocation.java:91) at com.jfinal.ext.interceptor.SessionInViewInterceptor.intercept(SessionInViewInterceptor.java:44) at com.jfinal.aop.Invocation.invoke(Invocation.java:91) at com.jfinal.core.ActionHandler.handle(ActionHandler.java:89) at com.jfinal.core.JFinalFilter.doFilter(JFinalFilter.java:89) at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1634) at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:533) at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:146) at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548) at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132) at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:257) at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1595) at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:255) at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1340) at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:203) at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:473) at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1564) at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:201) at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1242) at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:144) at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132) at org.eclipse.jetty.server.Server.handle(Server.java:503) at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:364) at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:260) at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:305) at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103) at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:118) at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:765) at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:683) at java.base/java.lang.Thread.run(Thread.java:835)

JFinal-4.7 action report -------- 2019-12-08 00:37:49 -------------------------- Url : POST /api/gets Controller : com.dathinking.gancao.controller.APIController.(APIController.java:1) Method : gets Interceptor : com.jfinal.ext.interceptor.SessionInViewInterceptor.(SessionInViewInterceptor.java:1) com.dathinking.gancao.jfinal.interceptor.CrosInterceptor.(CrosInterceptor.java:1) com.jfinal.ext.interceptor.POST.(POST.java:1)

TommyLemon commented 4 years ago

3.GET、HEAD请求是开放请求,可任意组合任意嵌套。其它请求为受限制的安全/私密请求,对应的 方法、tag、结构 都必须和 后端Request表中所指定的 一一对应,否则请求将不被通过。下同。

https://github.com/APIJSON/APIJSON/blob/master/Document.md#3.1

westerly-lzh commented 4 years ago

文档中根本就没有提到version的内容,而且我现在已经添加了version的信息,再次请求,仍然有错误 请求参数 { "[]":{ "User":{} }, "tag":"User", "version":1 }

后台数据库Request表记录: "1" 1 "GETS" "User" "{}" "允许任意内容" ""2019-12-01 00:00:00"" "2" 1 "HEADS" "User" "{}" "允许任意内容" ""2019-12-02 00:00:00""

前台仍是报错: { "[]": { "User": {} }, "code": 406, "msg": "GETS请求,请在 内传 User:{} !" }

后台异常信息如下: java.lang.IllegalArgumentException: GETS请求,请在 内传 User:{} ! at zuo.biao.apijson.server.Structure$1.onParseJSONObject(Structure.java:116) at zuo.biao.apijson.server.Structure.parse(Structure.java:303) at zuo.biao.apijson.server.Structure.parseRequest(Structure.java:109) at zuo.biao.apijson.server.AbstractParser.parseCorrectRequest(AbstractParser.java:466) at zuo.biao.apijson.server.AbstractParser.parseCorrectRequest(AbstractParser.java:622) at zuo.biao.apijson.server.AbstractParser.onVerifyContent(AbstractParser.java:423) at zuo.biao.apijson.server.AbstractParser.parseResponse(AbstractParser.java:332) at zuo.biao.apijson.server.AbstractParser.parseResponse(AbstractParser.java:306) at zuo.biao.apijson.server.AbstractParser.parse(AbstractParser.java:278) at com.dathinking.gancao.controller.APIController.gets(APIController.java:72) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:567) at com.jfinal.aop.Invocation.invoke(Invocation.java:97) at com.jfinal.ext.interceptor.POST.intercept(POST.java:30) at com.jfinal.aop.Invocation.invoke(Invocation.java:91) at com.dathinking.gancao.jfinal.interceptor.CrosInterceptor.intercept(CrosInterceptor.java:12) at com.jfinal.aop.Invocation.invoke(Invocation.java:91) at com.jfinal.ext.interceptor.SessionInViewInterceptor.intercept(SessionInViewInterceptor.java:44) at com.jfinal.aop.Invocation.invoke(Invocation.java:91) at com.jfinal.core.ActionHandler.handle(ActionHandler.java:89) at com.jfinal.core.JFinalFilter.doFilter(JFinalFilter.java:89) at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1634) at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:533) at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:146) at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548) at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132) at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:257) at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1595) at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:255) at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1340) at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:203) at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:473) at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1564) at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:201) at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1242) at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:144) at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132) at org.eclipse.jetty.server.Server.handle(Server.java:503) at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:364) at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:260) at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:305) at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103) at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:118) at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:765) at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:683) at java.base/java.lang.Thread.run(Thread.java:835)

westerly-lzh commented 4 years ago

经测试,在调用GETS时,使用如下参数可以得到返回值: { "User":{}, "tag":"User" } 但使用如下却抛出异常 { "[]":{ "User":{} }, "tag":"User" } 这和文档上说明的GET和GETS的区别只在最外层多了一个tag,明显不同。

经测试,在Structure类中方法public static JSONObject parse(String name, JSONObject target, JSONObject real, SQLCreator creator, @NotNull OnParseCallback callback) throws Exception中的一段代码如下: key = entry == null ? null : entry.getKey(); if (key == null) { continue; } tvalue = entry.getValue(); **rvalue = real.get(key);** if (callback.onParse(key, tvalue, rvalue) == false) { continue; } 如上中rvalue = real.get(key), 在我的测试用例中Key为User,那么如果使用如下参数调用GETS: { "[]":{ "User":{} }, "tag":"User" } 则会得到rvalue=null。导致Structure.onParseJSONObject抛出异常。

TommyLemon commented 4 years ago

在前端请求的 JSON 参数里,就只有 tag 的区别。 在后端解析的过程中,会用 tag 及 version 作为联合索引 查对应的 structure, 用 structure 指定的 JSON 结构及内容校验方式来对请求 JSON 校验。 如果 tag: value 中 value 符合表名格式,且 structure 缺少 value: {} 这个表对象, 则 AbstractParser. parseCorrectRequest 612 行会自动给 structure 对应的 JSON 包一层, 例如 tag 为 User,structure 为 {} ,则会把 {} 转为 "User": {} 来作为实际校验用的 structure。 https://github.com/APIJSON/APIJSON/blob/737a615e0d4c68061c929c8f5979644760caaa50/APIJSON-Java-Server/APIJSONORM/src/main/java/zuo/biao/apijson/server/AbstractParser.java

TommyLemon commented 4 years ago

关于 version 确实没在项目文档中说明,已更新: 3.GET、HEAD请求是开放请求,可任意组合任意嵌套。其它请求为受限制的安全/私密请求,对应的 method, tag, version, structure 都必须和 后端Request表中所指定的 一一对应,否则请求将不被通过。version 不传或为 null 会使用最高版本,传了有效值则会使用最接近它的最低版本。下同。

https://github.com/APIJSON/APIJSON/blob/master/Document.md#3.1

还可以看看这篇专门讲 APIJSON 自动化版本管理的博客 https://my.oschina.net/tommylemon/blog/1576587

TommyLemon commented 2 years ago

@westerly-lzh 现在 GETS 也支持数组了,例如 "[]":{"User":{}}

目前最新版是 5.0.0:

增强各种功能;腾讯负责人公开称赞;登记万科发起的采筑电商 https://github.com/Tencent/APIJSON/releases/tag/5.0.0

wyndem commented 6 months ago

@TommyLemon 似乎还是没用,是我哪里配置有问题吗? 版本为:6.3.0

image

image

image

TommyLemon commented 6 months ago

@wyndem

Request 表里 structure 配置必须是和请求传参一样结构的:

{
  "[]":{
    "C":{
    }
  }
}