RESTful API是目前比较成熟的一套互联网应用程序的API设计理论,规范了服务端资源的定义及访问。我们团队服务端就采用了RESTful。

  可是在现实开发过程中,还是有些问题。

  客户端在获取资源的时候,可能不同地方需要资源的不同的属性,而服务端常常会把几乎所有属性全部返回,这在App上会造成一些流量的浪费,譬如我要加载一个普通的产品列表,需要产品图片、产品名称、价格、库存等属性,而另一个浏览历史可能只需要名称和价格,这总不能写两个API吧?或者说附带一个请求参数告诉服务端要返回哪些属性,这倒行得通,可很不优雅。

  重要的是客户端还会有一个界面可能需要调用多个不同类型的资源的情况,最经典的就是电商App,个人中心界面里,既需要用户的一些信息,又要查询收藏数量、关注数量、足迹数量,又要查询不同状态下的订单数量,或者下方还有推荐商品列表。客户端一个界面请求多个资源URI会降低客户端的体验自然不好,或者需要服务端需要额外提供适配客户端的API能解决,可一旦界面有变化这些接口也要重新做适配。

  这些问题不是很重要,可问题多了,客户端开发和服务端开发要掐架。

  有没有相对好的解决办法呢?

  本人不才,搞了个 Jsonql(https://github.com/liyanjie8712/Jsonql,意图给RESTful按上一对翅膀。

  Jsonql是什么,咱给它起了个高大上的名字,Jsonql = Responsive Json Query Language,响应式Json查询语言,客户端要什么样的数据,由客户端来决定。服务端只提供资源及支持的查询函数,客户端编写查询请求,服务端解析并组装数据返回给客户端。这下服务端一劳永逸,客户端界面及数据绑定随便折腾去吧,挖哈哈~

  先来看看Jsonql的语法:

  变量的定义:$变量名

  变量必须先定义后使用,所有在定义前的引用都是错误的。
  变量具有作用域,只在当前定义它的 “{}” 及嵌套的子 “{}” 内有效,同时子作用域会覆盖父作用域定义的同名变量。

  例:$abc。

  资源的引用:资源名[]

  资源名必须与服务端公开的资源列表中的名称一致并区分大小写。

  例:users[]。

  方法的调用:.方法名(参数)

  例:.where(age>=18).count()。

  字段的访问:.字段名

  例:.user.name。

  资源的枚举:=>$

  使用资源访问符 “=>” 对资源进行枚举,“=>” 左侧定义资源的引用,右侧定义资源的输出(类似javascript对象)。
  如果右侧定义以 “[]” 结尾,则表示遍历资源输出一个数组,否则表示只输出索引为0的元素。
  “$” 表示对资源中元素的引用。
  定义输出时,输出字段与元素字段名称一致时,可以省略 “$.”。

  例:users[] => { uuid:$.id, name, age }

  使用表达式:{{表达式}}

  使用表达式可以执行一些运算操作,包括四则运算、逻辑运算、位运算等。 表达式必须使用“{{}}”包括,其运算结果为一个值。 表达式中可以使用变量,可以访问属性,但不可使用资源,不可调用方法。

  例:{{ 1 + 2 - 3 * 4 / 5 % 6 }}、{{ $abc > 0 }}、{{ true ? 1 : 0 }}

  写个查询的Demo,就拿用户与订单来:

 {
//获取用户信息
user: users[].where(id==1) =>
{
uuid: $.id, //ID
username, //用户名
avatar, //头像
account:
{
coins: $.account.coins,
points: $.account.points
}
},
//定义一个订单资源的变量
$orders: orders[].where(user.id==1),
//订单不同状态下的数量
orderCount:
{
created: $orders.count(status==1),
payed: $orders.count(status==2),
delivered: $orders.count(status==3),
completed: $orders.count(status==4)
},
//后去该用户的订单列表,前10条数据
orders: $orders.orderBy(createTime).skip(0).take(10) =>
{
uuid: $.id, //ID
serial, //订单号
status //订单状态
}[]
}

  将要返回什么数据呢?来看看:

 {
"user": {
"uuid": 1,
"username": "abcdefg",
"avatar": "http://img.xxxx.com/avatars/1.jpg",
"account": {
"coins": 8888,
"points": 9999
}
},
"ordercount": {
"created": 0,
"payed": 2,
"delivered": 1,
"completed": 18
},
"orders": [
{
"uuid": 1,
"serial": "00001",
"status": 2,
},
{
"uuid": 2,
"serial": "00002",
"status": 2,
},
//…………
]
}

  查什么返回什么,是不是方便多了?并且支持Linq Method,搞C#的童鞋是不是很眼熟?当然还支持动态表达式计算,譬如:

 {
$abc: 1,
$def: 2,
result: {{$abc + $def + 3}}
}

  返回结果:

 {
"result": 6
}

  Jsonql只是为了让查询更好用,资源的增删改操作还交给RESTful吧。

  就到这里。目前Jsonql支持AspNet与AspNetCore,GitHub里带有简单的Demo,有兴趣的童鞋可以下载下来玩一玩,相应的依赖包已发布到:http://myget.org/gallery/liyanjie。

  觉得不错就给颗星吧,另外欢迎大牛指导一二,不胜感激。

Jsonql——给RESTful API插上一对翅膀的更多相关文章

  1. 插上翅膀,让Excel飞起来——xlwings(二)

    在上一篇插上翅膀,让Excel飞起来——xlwings(一)中提到利用xlwings模块,用python操作Excel有如下的优点: xlwings能够非常方便的读写Excel文件中的数据,并且能够进 ...

  2. Spring Boot (六): 为 JPA 插上翅膀的 QueryDSL

    在前面的文章中,我们介绍了 JPA 的基础使用方式,<Spring Boot (三): ORM 框架 JPA 与连接池 Hikari>,本篇文章,我们由入门至进阶的介绍一下为 JPA 插上 ...

  3. 时序数据库(TSDB)-为万物互联插上一双翅膀

    本文由  网易云发布. 时序数据库(TSDB)是一种特定类型的数据库,主要用来存储时序数据.随着5G技术的不断成熟,物联网技术将会使得万物互联.物联网时代之前只有手机.电脑可以联网,以后所有设备都会联 ...

  4. 在Ubuntu上快速搭建基于Beego的RESTful API

    最近在研究Go,打算基于Go做点Web API,于是经过初步调研,打算用Beego这个框架,然后再结合其中提供的ORM以及Swagger的集成,可以快速搭建一个RESTful API的网站. 下面是具 ...

  5. restful api上传文件(基础)-springboot

    基于restful api格式的文件上传(只是上传到本地): package com.nxz.controller; import com.nxz.entity.FileInfo; import or ...

  6. 请求与上传文件,Session简介,Restful API,Nodemon

    作者 | Jeskson 来源 | 达达前端小酒馆 请求与上传文件 GET请求和POST请求 const express = require('express'); const app = expre ...

  7. Flask RESTful API搭建笔记

    之前半年时间,来到项目的时候,已经有一些东西,大致就是IIS+MYSQL+PHP. 所以接着做,修修补补,Android/iOS与服务器数据库交换用PHP, Web那边则是JS+PHP,也没有前后端之 ...

  8. 使用ASP.NET Core 3.x 构建 RESTful API - 1.准备工作

    以前写过ASP.NET Core 2.x的REST API文章,今年再更新一下到3.0版本. 先决条件 我在B站有一个非常入门的ASP.NET Core 3.0的视频教程,如果您对ASP.NET Co ...

  9. elasticsearch查询所有数据restful api以及java代码实现

    原文:http://blog.java1234.com/blog/articles/366.html restful api实现如下: get http://192.168.1.111:9200/fi ...

随机推荐

  1. css之描点定位方式

    <!-- 描点定位的两张方式 --> <!-- 1.通过id定位 --> <!-- 2.通过name定位 只能用a--> <div> <a hre ...

  2. Windows服务的创建、安装、卸载

    1.新建Window服务项目 2.添加安装配置文件 3.serviceProcessInstaller1右键属性,设置Account属性为LocalSystem. serviceInstaller1右 ...

  3. PROC UNIVARIATE过程

    EDA(探索性数据分析)最常用的过程步之一就是PROC UNIVARIATE. 首先先看一个最简单的PROC UNIVARIATE程序: PROC UNIVARIATE DATA=SASHELP.FI ...

  4. webAppbuilder微件使用教程3 地理处理微件

    webAppbuilder微件使用教程 --微件使用进阶地理处理微件 By 李远祥 地理处理是GIS解决问题的关键部分,也是其灵魂所在.由于WebAppBuilder框架的限制,用户如果想要非常灵活的 ...

  5. Nginx工作原理

    Nginx的模块 Nginx由内核和模块组成. Nginx的模块从结构上分为核心模块.基础模块和第三方模块: 核心模块:HTTP模块.EVENT模块和MAIL模块 基础模块:HTTP Access模块 ...

  6. d3.js 绘制极坐标图(polar plot)

    0.引言 在极坐标系中,任意位置可由一个夹角和一段相对原点(极点)的距离表示.也就是说,我们可以用 (angle,r) 来表示极坐标系中的点. 1.数据 假设我们有如下数据集[ [10, 0.2], ...

  7. 学习笔记——Java核心技术之接口、继承与多态练习题

    1.创建一个抽象类,验证它是否可以实例化对象. package com.lzw; public abstract class UseCase3 { abstract void doit(); publ ...

  8. angular : ng-animate : ng-show 原理,详解

    这是我第一次写博客,请大家多多指教^^ 拷贝试试 <!DOCTYPE html> <html> <head> <meta http-equiv="C ...

  9. MYSQL中添加时间

    1.在创建新记录和修改现有记录的时候都对这个数据列刷新:TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP 2.在创建新记录 ...

  10. mvc关于三级联动修改时数据回显

    在网上找了好久,都没有找到自己想要的那种效果,最后还是自己写出来了, 虽然方法有点笨. 这是Controller里 public ActionResult Edit(string id) { //查询 ...