-
Notifications
You must be signed in to change notification settings - Fork 2.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in 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: