Skip to content

Latest commit

 

History

History
49 lines (41 loc) · 21.4 KB

Document-English.md

File metadata and controls

49 lines (41 loc) · 21.4 KB

API Design Rules

1. Methods and API endpoints

 Methods URL Request Response
GET:
A general way to get data.
You can use dev tools to make edits in a web browser.
base_url/get/ {
   TableName:{
     //Add contiditions here.
   }
}

Eg. To get a Moment with id = 235
{
   "Moment":{
     "id":235
   }
}
{
   TableName:{
     ...
   },
   "code":200,
   "msg":"success"
}
Eg.
{
   "Moment":{
     "id":235,
     "userId":38710,
     "content":"APIJSON,let interfaces and documents go to hell !"
   },
   "code":200,
   "msg":"success"
}
HEAD:
A general way to get counts.
You can use dev tools to make edits in a web browser.
base_url/head/ {
   TableName:{
     …
   }
}
{…} are conditions.

Eg. Get the number of Moments posted by the user with id = 38710
{
   "Moment":{
     "userId":38710
   }
}
{
   TableName:{
     "code":200,
     "msg":"success",
     "count":10
   },
   "code":200,
   "msg":"success"
}
Eg.
{
   "Moment":{
     "code":200,
     "msg":"success",
     "count":10
   },
   "code":200,
   "msg":"success"
}
GETS:
Get data with high security and confidentiality.
Eg. bank accounts, birth date.
base_url/gets/ You need to add "tag":tag with the same level of Moment:{}. Others are the same as GET. Same as GET.
HEADS:
Get counts of confidential data(eg. bank account).
base_url/heads/ You need to add "tag":tag with the same level of Moment:{}. Others are the same as HEAD. Same as HEAD.
POST:
Add new data.
base_url/post/ {
   TableName:{
     …
   },
   "tag":tag
}
The id in {...} is generated automatically when table is built and can’t be set by the user.

Eg. A user with id = 38710 posts a new Moment:
{
   "Moment":{
     "userId":38710,
     "content":"APIJSON,let interfaces and documents go to hell !"
   },
   "tag":"Moment"
}
{
   TableName:{
     "code":200,
     "msg":"success",
     "id":38710
   },
   "code":200,
   "msg":"success"
}
Eg.
{
   "Moment":{
     "code":200,
     "msg":"success",
     "id":120
   },
   "code":200,
   "msg":"success"
}
PUT:
Make changes to a specific item.
Only change the part sent to server.
base_url/put/ {
   TableName:{
     "id":id,
     …
   },
   "tag":tag
}
You can also add multiple id as id{}.

Eg. Make changes to Moment's content with id= 235:
{
   "Moment":{
     "id":235,
     "content":"APIJSON,let interfaces and documents go to hell !"
   },
   "tag":"Moment"
}
Same as POST.
DELETE:
Delete data.
base_url/delete/ {
   TableName:{
     "id":id
   },
   "tag":tag
}
You can also add multiple id as id{}.

Or Delete contents with multiple id:
{
   "Comment":{
     "id{}":[100,110,120]
   },
   "tag":"Comment[]"
}
{
   TableName:{
     "code":200,
     "msg":"success",
     "id[]":[100,110,120]
      "count":3
   },
   "code":200,
   "msg":"success"
}
Eg.
{
   "Comment":{
      "code":200,
      "msg":"success",
      "id[]":[100,110,120],
      "count":3
   },
   "code":200,
   "msg":"success"
}

Note:

  1. TableName means the name of the table where you get data. It’ll respond with a JSON Object(the form is {....})with columns inside.
  2. "tag":tag is needed when methods are not GET or HEAD. The tag after the colon is the key in JSON Object of making requests. Generally, it’s the name of the table you’re looking for.
  3. GET, HEAD are methods for general data requests.They support versatile JSON Object structure. Other methods are used for requesting confidential data and the requesting JSON Object needs to be in the same form/order as that in the database. Otherwise, the request shall be denied.
  4. GETS and GET, HEADS and HEAD return the same type of data. But the request form is a little different.
  5. For HTTP, all API methods (get,gets,head,heads,post,put,delete) make requests with HTTP POST.
  6. All JSON Objects here are with {...} form. You can put items or objects in it.
  7. Each object in the database has a unique address.

2. Keyswords in URL parameters

Functions Key-value pairs Examples
Get data in arrays "key[]":{}
The part after the colon is a JSONObject. key is optional. When key is the same as the table name , the JSONObject will be in a simplified form. For example, {Table:{Content}} will be written as {Content}.
{"User[]":{"User":{}}}
It is used for getting data from a user. Here, key and tablename are all "User", then
{"User":{"id", ...}}
will be written as
{"id", ...}
Get data that meets specific conditions "key{}":[]
The part after the colon is a JSONArray with conditions inside.
"id{}":[38710,82001,70793]
In SQL, this would be id IN(38710,82001,70793).
It means getting data with id equals 38710,82001,70793.
Get data with comparison operation "key{}":"condition0,condition1..."
Conditions can be any SQL comparision operation. Use''to include any non-number characters.
"id{}":"<=80000,>90000"
In SQL, it'd be
id<=80000 OR id>90000,
which means get User array with id<=80000 | id>90000
Get data that contains an element "key<>":Object => "key<>":[Object]
key must be a JSONArray while Object cannot be JSON.
"contactIdList<>":38710
In SQL, this would be
json_contains(contactIdList,38710).
It means find data of the User whose contactList contains 38710.
See if it exists "key}{@":{
   "from":"Table",
   "Table":{ ... }
}

}{ means EXISTS.
key is the one you want to check.
Here is a Subquery in it, see specifications below for more information.
"id}{@":{
   "from":"Comment",
   "Comment":{
      "momentId":15
   }
}

WHERE EXISTS(SELECT * FROM Comment WHERE momentId=15)
Include functions in parameters "key()":"function (key0,key1...)"
This will trigger the back-end
function(JSONObject request, String key0, String key1...)
to get or testify data.
Use - and + to show the order of priority: analyze key-() > analyze the current object > analyze key() > analyze child object > analyze key+()
"isPraised()":"isContain(praiseUserIdList,userId)"
This will use function boolean isContain(JSONObject request, String array, String value). In this case, client will get "isPraised":true(In this case, client use function to testify if a user clicked ‘like’ button for a Moment.)
Refer a value "key@":"key0/key1/.../refKey"
Use / to show path. The part before the colon is the key that wants to refer. The path after the colon starts with the parent level of the key.
"Moment":{
   "userId":38710
},
"User":{
   "id@":"/Moment/userId"
}

In this example, the value of id in User refer to the userId in Moment, which means
User.id = Moment.userId.
After the request is sent,
"id@":"/Moment/userId" will be "id":38710.
Subquery "key@":{
   "range":"ALL",
   "from":"Table",
   "Table":{ ... }
}
range can be ALL, ANY.
from means which table you want to query.
It’s very similar to how you query in SQL.
You can also use count, join, etc.
"id@":{
   "from":"Comment",
   "Comment":{
      "@column":"min(userId)"
   }
}

WHERE id=(SELECT min(userId) FROM Comment).
Fuzzy matching "key$":"SQL search expressions" => "key$":["SQL search expressions"]
Any SQL search expressions.Eg.%key%(include key), key%(start with key),%k%e%y%(include k, e, y). % means any characters.
"name$":"%m%"
In SQL, it's
name LIKE '%m%',
meaning that get User with ‘m’ in name.
Regular Expression "key~":"regular expression" => "key~":["regular expression"]
It can be any regular expressions.Eg. ^[0-9]+$ ,*~ not case sensitive, advanced search is applicable.
"name~":"^[0-9]+$"
In SQL, it's
name REGEXP '^[0-9]+$'.
Get data in a range "key%":"start,end" => "key%":["start,end"]
The data type of start and end can only be either Boolean, Number or String. Eg. "2017-01-01,2019-01-01" ,["1,90000", "82001,100000"]. It's used for getting data from a specific time range.
"date%":"2017-10-01,2018-10-01"
In SQL, it's
date BETWEEN '2017-10-01' AND '2018-10-01',
meaning to get User data that registered between 2017-10-01 and 2018-10-01.
Make an alias "name:alias"
this changes name to alias in returning results. It’s applicable to column, tableName, SQL Functions, etc. but only in GET, HEAD requests.
"@column":"toId:parentId"
In SQL, it's
toId AS parentId.
It'll return parentId instead of toId.
Add / expand an item "key+":Object
The type of Object is decided by key. Types can be Number, String, JSONArray. Froms are 82001,"apijson",["url0","url1"] respectively. It’s only applicable to PUT request.
"praiseUserIdList+":[82001]. In SQL, it's
json_insert(praiseUserIdList,82001).
Add an id that praised the Moment.
Delete / decrease an item "Key-":Object
It’s the contrary of "key+"
"balance-":100.00. In SQL, it's
balance = balance - 100.00,
meaning there's 100 less in balance.
Operations &, |, !
They're used in logic operations. It’s the same as AND, OR, NOT in SQL respectively.
By default, for the same key, it’s ‘|’ (OR)operation among conditions; for different keys, the default operation among conditions is ‘&’(AND).
"id&{}":">80000,<=90000"
In SQL, it's
id>80000 AND id<=90000,
meaning id needs to be id>80000 & id<=90000

"id|{}":">90000,<=80000"
It's the same as "id{}":">90000,<=80000".
In SQL, it's
id>80000 OR id<=90000,
meaning that id needs to be id>90000 | id<=80000

"id!{}":[82001,38710]
In SQL, it's
id NOT IN(82001,38710),
meaning id needs to be ! (id=82001 | id=38710).
Keywords in an Array: It can be self-defined. As for "key":Object, key is the keyword of {} in "[]":{}. The type of Object is up to key.

"count":Integer It's used to count the number. The default largest number is 100.

"page":Integer It’s used for getting data from which page, starting from 0. The default largest number is 100. It’s usually used with COUNT.

"query":Integer Get the number of items that match conditions
When to get the object, the integer should be 0; when to get the total number, it’s 1; when both above, it’s 2.
You can get the total number with keyword total. It can be referred to other values.
Eg.
"total@":"/[]/total"
Put it as the same level of query.
Query and total are used in GET requests just for convenience. Generally, HEAD request is for getting numbers like the total number.

"join":"&/Table0/key0@,</Table1/key1@"
Join tables:
"<" - LEFT JOIN
">" - RIGHT JOIN
"&" - INNER JOIN
"|" - FULL JOIN
"!" - OUTER JOIN
"@" - APP JOIN
Where @ APP JOIN is in application layer.It’ll get all the keys in tables that refKeys in result tables are referred to, like refKeys:[value0, value1….]. Then, as the results get data according to key=$refKey a number of times (COUNT), it uses key IN($refKeys) to put these counts together in just one SQL query, in order to improve the performance.
Other JOIN functions are the same as those in SQL.
"join":"</ViceTable/key@",
"MainTable":{},
"ViceTable":{"key@":"/MainTable/refKey"}
will return
MainTable LEFT JOIN ViceTable
ON ViceTable.key=MainTable.refKey

"otherKey":Object Self-defined keyword other than those that already in the system. It also returns with self-defined keywords.
① Get User arrays with maximum of 5:
"count":5

② Look into User arrays on page 3. Show 5 of them each page.
"count":5,
"page":3


③ Get User Arrays and count the total number of Users:
"[]":{
   "query":2,
   "User":{}
},
"total@":"/[]/total"

Questions like total page numbers or if there's next page can be solved by total,count,page functions,
Total page number:
int totalPage = Math.ceil(total / count)
If this is the last page:
boolean hasNextPage = total > count*page
If this is the first page:
boolean isFirstPage = page <= 0
If it's the last page:
boolean isLastPage = total <= count*page
...

④ Moment INNER JOIN User LEFT JOIN Comment:
"[]":{
   "join": "&/User/id@,</Comment/momentId@",
   "Moment":{},
   "User":{
     "name~":"t",
     "id@": "/Moment/userId"
   },
   "Comment":{
     "momentId@": "/Moment/id"
   }
}


⑤ Add the current user to every level:
"User":{},
"[]":{
   "name@":"User/name", //self-defined keyword
   "Moment":{}
}
Keywords in Objects: It can be self-defined. "@key":Object @key is the keyword of {} in Table:{}. The type of Object is decided by @key

"@combine":"&key0,&key1,|key2,key3,
!key4,!key5,&key6,key7..."
First, it’ll group data with same operators. Within one group, it operates from left to right. Then it’ll follow the order of & | ! to do the operation. Different groups are connected with &. So the expression above will be :
(key0 & key1 & key6 & other key) & (key2 | key3 | key7) & !(key4 | key5)
| is optional.

"@column":"column;function(arg)..." Return with specific columns.

"@order":"column0+,column1-..." Decide the order of returning results:

"@group":"column0,column1..." How to group data. If @column has declared Table id, this id need to be included in @group. In other situations, at least one of the following needs to be done:
1.Group id is declared in @column
2.Primary Key of the table is declared in @group.

@having":"function0(...)?value0;function1(...)?value1;function2(...)?value2..." Add conditions on return results with @having. Usually working with@group, it’s declared in @column.

"@schema":"sys" Can be set as default setting.

"@database":"POSTGRESQL" Get data from a different database.Can be set as default setting.

"@role":"OWNER" Get information of the user, including
UNKNOWN,LOGIN,CONTACT,CIRCLE,OWNER,ADMIN,
Can be set as default setting.
You can self-define a new role or rewrite a role. UseVerifier.verify etc. to self-define validation methods.

"@explain":true Profiling. Can be set as default setting.

"@otherKey":Object Self-define keyword
① Search Users that name or tag contains the letter "a":
"name~":"a",
"tag~":"a",
"@combine":"name~,tag~"


② Only search column id,sex,name and return with the same order:
"@column":"id,sex,name"

③ Search Users that have descending order of name and default order of id:
"@order":"name-,id"

④ Search Moment grouped with userId:
"@group":"userId,id"

⑤ Search Moments that id equals or less than 100 and group with userId:
"@column":"userId;max(id)",
"@group":"userId",
"@having":"max(id)>=100"

You can also define the name of the returned function:
"@column":"userId;max(id):maxId",
"@group":"userId",
"@having":"maxId>=100"


⑥ Check Users table in sys:
"@schema":"sys"

⑦ Check Users table in PostgreSQL:
"@database":"POSTGRESQL"

⑧ Check the current user's activity:
"@role":"OWNER"

⑨ Turn on profiling:
"@explain":true

⑩ Get the No.0 picture from pictureList:
"@position":0, //self-defined keyword
"firstPicture()":"getFromArray(pictureList,@position)"