-
Notifications
You must be signed in to change notification settings - Fork 2.2k
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
How to make another APIJSON? / 如何实现其它语言的APIJSON? #38
Comments
建议步骤: 1.实现单表查询{
"User": {
"id": 82002
}
} 转换为 SELECT * FROM User WHERE id = 82002 LIMIT 1 OFFSET 0 ResultSet取第0条(总数最多1条),取出所有字段对应的值,封装为一个表对象返回: {
"id": 82002,
"sex": 1,
"name": "Happy~",
"tag": "iOS",
"head": "http://static.oschina.net/uploads/user/1174/2348263_50.png?t=1439773471000",
"contactIdList": [
82005,
82001,
38710
],
"pictureList": [],
"date": "2017-02-01 19:21:50.0"
} 替换原来的 {
"id": 82002
} 2.实现数组查询{
"[]": {
"count": 10,
"page": 1,
"User": {
"sex": 1
}
}
} 转换为 SELECT * FROM User WHERE sex = 1 LIMIT 10 OFFSET 10 ResultSet取所有,封装为一个包含表对象的数组返回: [
{
"User": {
"id": 82005,
"sex": 1,
"name": "Jan",
"tag": "AG",
"head": "http://my.oschina.net/img/portrait.gif?t=1451961935000",
"contactIdList": [
82001,
38710
],
"pictureList": [],
"date": "2017-02-01 19:21:50.0"
}
},
{
"User": {
"id": 82006,
"sex": 1,
"name": "Meria",
"head": "http://static.oschina.net/uploads/user/998/1997902_50.jpg?t=1407806577000",
"contactIdList": [],
"pictureList": [],
"date": "2017-02-01 19:21:50.0"
}
}
] 替换原来的 {
"count": 10,
"page": 1,
"User": {
"sex": 1
}
} 3.实现两张表 一对一 关联查询{
"Comment": {},
"User": {
"id@": "Comment/userId"
}
} 先解析Comment,转换为 SELECT * FROM Comment LIMIT 1 OFFSET 0 ResultSet取第0条(总数最多1条),取出所有字段对应的值,封装为一个Comment表对象返回: {
"id": 4,
"toId": 0,
"userId": 38710,
"momentId": 470,
"date": "2017-02-01 19:20:50.0",
"content": "This is a Content...-4"
} 然后解析User,解析到 "id@": "Comment/userId" 时,从Comment中取出userId,把以上键值对改为
然后把User转换为 SELECT * FROM User WHERE id = 38710 LIMIT 1 OFFSET 0 ResultSet取第0条(总数最多1条),取出所有字段对应的值,封装为一个User表对象返回: {
"id": 38710,
"sex": 0,
"name": "TommyLemon",
"tag": "Android&Java",
"head": "http://static.oschina.net/uploads/user/1218/2437072_100.jpg?t=1461076033000",
"contactIdList": [
82003,
82005,
70793
],
"pictureList": [
"http://static.oschina.net/uploads/user/1218/2437072_100.jpg?t=1461076033000",
"http://common.cnblogs.com/images/icon_weibo_24.png"
],
"date": "2017-02-01 19:21:50.0"
} 4.实现两张表 一对多 关联查询{
"Moment": {},
"[]": {
"Comment": {
"momentId@": "Moment/id"
}
}
} 5.实现两张表在数组内 一对一 关联查询{
"[]": {
"Comment": {},
"User": {
"id@": "[]/Comment/userId"
}
}
} 其中 "id@": "[]/Comment/userId" 要根据Comment在数组中的位置index来动态变为 "id@": "[]/0/Comment/userId" "id@": "[]/1/Comment/userId" ... 6.实现两张表在数组内 一对多 关联查询实现了 1-6 后可以测试是否能通过这个用例(一对一、一对多、数组外、数组内、同层级、跨层级都有) POST http://apijson.cn:8080/get {
"Moment": {
"id": 32,
"@column": "id,userId,praiseUserIdList"
},
"User": {
"id@": "Moment/userId",
"@column": "id"
},
"[]": {
"Moment": {
"userId{}@": "Moment/praiseUserIdList",
"@column": "id,userId"
},
"User": {
"id@": "/Moment/userId",
"@column": "id,name,head"
},
"Comment[]": {
"Comment": {
"momentId@": "[]/Moment/id"
}
}
}
} 7.实现SQL的 column, order by, group by等功能。8.实现增、删、改APIAuto 上有 200 左右测试用例,可以跑一遍看看哪些有问题 测试数据 SQL 文件(MySQL, PostgreSQL, Oracle, SQL Server, DB2, ClickHouse 等) 完整功能见设计规范(核心的任意多表关联查询功能完成后可逐步完善其它功能) |
由于不限制嵌套层级和组合方式,所以必须用递归实现,从数据库查到结果(一开始可模拟测试数据,省去连接数据库的过程)后替换掉原来的内容再返回。 递归时由于不知道键值对key:value中的key和value,所以需要判断key和value的格式。 {
"[]": { // value 类型为 JSONObject && key 以 [] 结束
"User": { // value 类型为 JSONObject && key 符合正则表达式 ^[A-Za-z]+$
"sex": 1 // value 类型不为 JSONObject
}
}
} |
最简单的解析过程可以是:1.Parser递归遍历 请求JSON,提取出每个 表对象JSON |
APIJSON-C# Server: |
上回说的python初步完成了 https://github.com/zeromake/restful_model 刚刚把单元测试写好。 import sqlalchemy as sa
from sanic import Sanic
from restful_model import DataBase
from restful_model.extend.sanic import ApiView
metadata = sa.MetaData()
# 这个model可以直接用工具连接数据库生成
User = sa.Table(
'user',
metadata,
sa.Column(
'id',
sa.Integer,
autoincrement=True,
primary_key=True,
nullable=False,
),
sa.Column(
'account',
sa.String(16),
nullable=False,
),
sqlite_autoincrement=True,
)
# python 可以动态生成 class 后面想批量注册model到view也很简单
class UserView(ApiView):
__model__ = User
# 请求方法过滤
# __method__ = ["get", "post"]
# 过滤 where 或者查询字段,支持全局或单个方法过滤
#__filter_keys__ = {"get": [["id"]]}
# 中间件模式
async def auth_filter(self, context: Context, next_filter):
return await next_filter()
app = Sanic(__name__)
db = DataBase("sqlite:///db.db")
app.db = db
@app.listener('before_server_start')
async def setup_db(app, loop):
if app.db.loop is None:
app.db.loop = loop
app.db.engine = await app.db.create_engine(echo=True)
if not await app.db.exists_table(User.name):
await app.db.create_table(User)
userView = UserView.as_view(app.db)
app.add_route(userView, "/user", HTTP_METHODS)
app.add_route(userView, "/user/<id:int>", HTTP_METHODS)
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8000) $ # create
$ curl -X POST http://127.0.0.1:8000/user \
-H 'content-type: application/json' \
-d '{ "account": "test1" }'
> {
"status": 201,
"message": "Insert ok!",
"meta": {"count":1}
}
$ # select
$ curl -X GET http://127.0.0.1:8000/user
> {
"status": 200,
"message": "Query ok!",
"data": [{
"id": 1,
"account": "test1"
}]
}
$ # update
$ curl -X PUT http://127.0.0.1:8000/user \
-H 'content-type: application/json' \
-d '{"where": {"id": 1}, "values": {"account": "test2"}}'
> {
"status": 201,
"message": "Update ok!",
"meta":{
"count": 1
}
}
$ curl -X GET http://127.0.0.1:8000/user
> {
"status": 200,
"message": "Query ok!",
"data": [
{"id": 1,"account": "test2"}
]
}
$ # delete
$ curl -X DELETE http://127.0.0.1:8000/user \
-H 'content-type: application/json' \
-d '{"id": 1}'
> {
"status": 200,
"message": "Delete ok!",
"meta": {"count":1}
}
$ curl -X GET http://127.0.0.1:8000/user
> {
"status": 200,
"message": "Query ok!",
"data": []
} 现在还是觉得权限管理不太给力,虽然用中间件模式,什么样的权限都做的了。 以及多表连接在想是提供一个 class 然后把多张表设置上去,url 和权限独立,还是像你的 后面有心情再考虑把 json 的表现层抽出来,做了 |
@zeromake 赞,已Star。 {
"User": {
"id": 70793
}
} {
"Moment": {
"id": 12
}
} ... {
"Moment": {
"id": 12
},
"User": {
"id": 70793
}
} 不知道User.id的情况下可以通过 引用赋值 得到 {
"Moment": {
"id": 12
},
"User": {
"id@": "Moment/userId" // User.id = Moment.userId
}
} {
"Moment": {
"id": 12
},
"[]": {
"User": {
"id{}@": "Moment/praiseUserIdList" // json_contains(Moment.praiseUserIdList, User.id)
}
}
} |
@zeromake 你改好后我就在APIJSON主页加上这个项目的链接哈,和 C#版 一样 |
@TommyLemon 我这个只是为了做基础控件的,对应某个表操作,全局可连接任意表的应当后面做一个单独的控制 view,全部由使用的人来选择是注册一个全局 url 进行控制,还是挂几个表view。后面都会做对应的包括单表和 APIJSON 的相同的全局可连接任意表。 |
@zeromake 这样啊,非常期待,记得通知我哦,有问题欢迎找我交流 |
@TommyLemon |
@zeromake 可以 |
APIJSON Node.js 版,基于 typeorm ,使用 TypeScript 实现。 创作不易,给热心的作者右上角点 ⭐Star 支持下吧 ^_^ |
已赞 @TommyLemon |
已经有热心的开发者实现了 PHP 版的 APIJSON 🎉 |
@TommyLemon 这个PHP版没有实现吧... |
建议出一个功能清单.md,放在每个语言实现的代码库里,实现的功能就划掉,这样比较清晰. |
有没有打算做非关系数据库mongodb的 |
@yuhongshuai 暂时没有计划,后续可能支持。 |
已经有热心的开发者实现了 Python 版的 APIJSON 🎉 创作不易,给作者点 ⭐Star 支持下吧^_^ |
@never615 |
APIJSON Go 语言版 APIJSON |
@never615 @SwankyTigerYY @y449329998 @ben1one |
@TommyLemon 我想问一下,生成的SQL是有基于什么标准吗? 怎么才能做到生成的SQL兼容各种数据库? |
@jimisun123 |
目前已有 C#, Go, Java, Node, PHP, Python 对应的 APIJSON ORM 库实现
https://github.com/Tencent/APIJSON#%E7%94%9F%E6%80%81%E9%A1%B9%E7%9B%AE
一开始不要贪大求全,实现基础的功能就好,功能后面再完善、性能后面再优化。
可以参考Java版的实现,建议从这个版本做起
https://github.com/TommyLemon/APIJSON/tree/636fe2263c01acce4ad32751cbb8a579830d9f29
这个是最简单的实现,只有7个类,将JSON转换为SQL,但也能够实现最核心的 引用赋值、单表查询、数组分页查询 了。
先完成这个,后面再优化。如果直接实现复杂功能,很可能导致一大堆问题然后坚持不下去。
The text was updated successfully, but these errors were encountered: