![]() | 1 matthewgao 2015-09-17 08:55:57 +08:00 via Android 通常用 json |
![]() | 2 crs0910 2015-09-17 08:56:33 +08:00 这是什么意思?不是 GET 和 POST 吗? |
![]() | 3 vainly 2015-09-17 08:57:09 +08:00 如果是 GET 请求,请求参数要在请求地址后"http://ip:port/doman?a=1&b=1&c=1" 如果是 POST 请求,而且交互使用 JSON 数据格式的话,参数传递会是这样的"{a:1,b=2,c=3,...}" |
4 mithvv 2015-09-17 09:22:22 +08:00 get a=1&b=2&arr[]=3&arr[]=4 post { a:1,b:2,c:[3,4] } |
5 morethansean 2015-09-17 09:24:52 +08:00 POST 传出去不还是 a=1&b=c 除非你是自定义的 value 值是 json 格式比如 a=1&b=%7Bc%3A%205%7D > decodeURIComponent ('%7Bc%3A%205%7D') > "{c: 5}" |
6 jhaohai 2015-09-17 09:32:03 +08:00 json ,感觉已经成为标准了 |
7 wshcdr 2015-09-17 09:33:13 +08:00 json 已经是事实上的标准了 |
![]() | 8 learnshare 2015-09-17 10:00:16 +08:00 JSON 几乎作为标准存在了,虽然数据量会大一些 |
![]() | 9 temberature OP |
10 morethansean 2015-09-17 10:08:42 +08:00 不管你提交是否是 JSON ,转换总是需要的,特别是提交数据肯定是需要经过服务器端校验和安全处理的。 而且大多时候提交的数据又不是直接丢数据库去储存的,增删查找需要的字段,和返回的结果本来有些时候就相差甚远,处理逻辑也完全不一样,没必要强行 JSON 格式。 |
![]() | 11 temberature OP @morethansean 我说的转换是指这两种字符串能表达的数据结构是等价的,如果只有一种,只需要在一种交换数据和程序变量之间转换。我没有说一定要用什么,只是想知道请教下是否有区别,以及各自的利弊又是什么? |
![]() | 12 temberature OP @learnshare 感觉都浪费在双引号上了 |
![]() | 13 matthewgao 2015-09-17 10:33:15 +08:00 @vainly ”如果是 GET 请求,请求参数要在请求地址后"http://ip:port/doman?a=1&b=1&c=1" “ 这个似乎不是很符合 RESTful 的建议吧 |
![]() | 14 lyz1990 2015-09-17 10:36:19 +08:00 json ,事实标准 |
![]() | 15 temberature OP |
16 hantsy 2015-09-17 10:46:29 +08:00 ![]() @temberature 首先搞清楚什么是 REST 。 InfoQ 上有 Fielding 博士的原始论文的中文翻译版本。 广泛的讲 REST 不限于 HTTP 协议,数据交换格式可以是文本也可以是二进制。狭义的讲,我们通常将 REST 限于 HTTP , JSON 是取常用的数据交换格式, XML 也没问题。 REST 的几个要素: 1. 用一个唯一的 URI 代表资源的定位 2. 用 HTTP 语义( GET , POST , PUT , PATCH , DELETE , HEAD , OPTION 等)操作资源 3. 用 HTTP 状态标志操作结果 常用的 CRUD REST API 可以这样设计: 比如常见的 BLOG 程序,定义一个 /posts 入口。 /posts , GET , 取得所有 POST ,结果是一个 [{},{}]数组,可以接查询参数?page=XXX 等,返回 200 状态。 /posts , POST , 发布新 POST , Request Body 为{title:"text", body:"test body"}, 返回 201 状态。 /posts /{id}, GET , 取得所有单个 POST , URI 需要接 id, 成功返回 200 状态,失败 404 。 /posts /{id} , PUT , 更新 POST , Request Body 为{title:"text", body:"test body"}, 返回 204 状态。 /posts /{id} , DELETE , 删除 POST , 成功 返回 204 状态。 /posts 是对资源集合操作,/posts/{id}对单个资源操作。操作的结果有的有返回数据,更直接的表达结果是 HTTP Status 。 我写的简单的例子, https://github.com/hantsy/angularjs-springmvc-sample 这个例子,目前没写任何 Notes 来描述。 要了解 REST API 实现,可以看另外一个类似的例子 https://github.com/hantsy/angularjs-grails-sample , 这个项目的 WIKI 上的详细介绍。 @temberature 从 REST API 设计角度,你的问题和 REST 一点关系都没有。从设计上角度,查询数据?a=1 仅适用条件过滤,也就是上面第一个 /posts GET 方式。 另外,关于 REST API 设计好坏,有一个 Rechardson 成熟度模型来衡量。它定义了三个级别。国内几个一线大公司的 API 基本都是 Level 0 , 按这个标准衡量来讲,都不是 REST API ,虽然他们 Developer 网站都喜欢写上 REST 的字样。反而一些不大的公司做得不错,比如 JPUSH 等。 当我们考虑 Level3 ( Self-document, Self-Discovery ) 的时候,在交换格式上就有很多细节要去实现。这方面有一些行业标准或者正在标准化的交换格式。 如: HAL , Collection+JSON , JSON API 。 |
17 hantsy 2015-09-17 10:51:09 +08:00 @matthewgao GET 是用于查询操作,是可以使用 query parameters 的。 |
18 hantsy 2015-09-17 10:52:31 +08:00 ![]() @temberature JSON API 目前应用范围不广,不如 HAL 流行, Spring 目前只支持 HAL 。 |
19 refear99 2015-09-17 10:52:57 +08:00 取就用 get+query 增删改就用 POST DELETE PUT + json body |
![]() | 20 temberature OP @hantsy 博士的论文我翻过几次,我知道数据交换并不是 rest 的主要关注点,只要想请教下在实际的做法以及如何取舍,感谢分享~ |
21 hantsy 2015-09-17 11:12:24 +08:00 @temberature 我上面两个链接的例子中 UI 全部是 SPA 。 |
![]() | 22 gamexg 2015-09-17 11:28:38 +08:00 直接 command_json , sign 。 a=1&b=2 这种做 hash 签名容易被坑死。 |
![]() | 23 temberature OP @gamexg 没太明白,能再具体解释下吗:) |
![]() | 24 loading 2015-09-17 11:56:21 +08:00 via Android 如果省流量你考虑进去,这问题就没必要讨论了。 hash 你后面掉坑就知道了。 |
![]() | 25 temberature OP @loading 清楚利弊,在具体情况下就好取舍了吧;能描述下这个坑的大小、颜色、气味吗?以免掉下水道里,哈哈~ |
![]() | 26 gamexg 2015-09-17 12:31:24 +08:00 比如一些 http 请求为了安全需要做 hash 签名, a=1&b=2 这种签名会碰到很多坑。 看一下这个 hash 签名设计: https://blog.yanke.io/she-ji-yi-tao-ji-yu-hash-qian-ming-yan-zheng-de-api/ ``` 因此我初步设计了一个签名机制,步骤如下: 将时间戳,随机串, TokenID ,和业务逻辑关键参数构成一个字典 将字典按照 Key 升序排序,然后按照 key1 value1 key2 value2 拼成一个连续字符串 将 Path 拼在前面, Token 拼在后面 将整个字符串做 SHA256 ,作为一个参数放回到请求中 服务器端接收到请求的时候也进行同样的处理,进行签名验证。 如果你曾经裸写过常见的第三方服务 API 调用的话,你会对这些步骤非常熟悉。 ``` 如果直接传递 json 字符串,直接 hash json 字符串即可,不用麻烦的拼接了。 |
![]() | 27 temberature OP @gamexg 只理解到处理方式的差别,没看到坑 |
![]() | 28 wangleineo 2015-09-17 12:48:48 +08:00 ![]() 还是统一用 JSON 好些吧,用 Form 提交的话,多层数据怎么办? |
![]() | 29 FrankFang128 2015-09-17 12:49:53 +08:00 都支持就好了 |
![]() | 30 temberature OP @FrankFang128 这样只是把问题抛给了调用接口方吧 |
31 hantsy 2015-09-17 12:56:33 +08:00 @gamexg 难道不用 HTTPS 吗?签名这东西,看着就吐,根本谈不上安全,如果你的 Token 被截取(没 HTTPS 所有数据传输都透明), Hacker 构造你这样顺序的签名有什么难的。这也是 oAuth2 去掉了签名,强制使用 HTTPS 的原因。 |
![]() | 32 marginleft 2015-09-17 12:59:30 +08:00 |
33 pandada8 2015-09-17 13:00:14 +08:00 不是取决于 Accept 头的么…… |
34 pandada8 2015-09-17 13:04:40 +08:00 |
![]() | 35 iyaozhen 2015-09-17 13:20:46 +08:00 这个取决于你的操作吧。 GET 获取数据,可以用 urlencode 传参。 POST 用于更改数据,传 json 更合适吧。 |
![]() | 36 temberature OP @pandada8 如果接口是不同的人在写,那还要看是谁方便,有一套参考的规范会更好吧 |
![]() | 37 aftereclipse 2015-09-17 13:41:51 +08:00 统一 HTTP POST , json 数据格式,客户端和服务端都好写,加解密也好做 |
![]() | 38 vainly 2015-09-17 14:04:11 +08:00 @matthewgao 不是啊,对于指定参数的 GET 请求时这么做的。 比如这样: @GET @Path ("findById") public String findById (@QueryParam ("id")String id ); |
![]() | 39 temberature OP @vainly 没看懂,() |
40 pandada8 2015-09-17 14:26:06 +08:00 @temberature 最后当然要统一了……之前先做好协定。 比如有 angular,superagent 之类的场合我倾向于使用 json 有些时候框架搭配用 jquery 发请求那就用 form-urlencoded. 总体而言就是怎么方便怎么来 实在决定不了么 来局昆特牌吧 |
![]() | 41 gamexg 2015-09-17 14:28:20 +08:00 @temberature 你需要保证前后端的排序、编码等是一致的。记得有一篇 API 文档提到过,个别语言的排序和 API 服务器不一致,需要特殊处理。 @hantsy 即使上了 https ,我也会利用类似签名的方式而不会直接传递 API 密钥做身份认证的。例如目前对于设备的认证就是设备注册时分配一个 id 及密钥,每个请求都会被 hash 签名。密钥只会在设备注册时传递一次,之后不会传递,这个风险还是可以接受的。由于密钥不像密码,更换麻烦,后期即使加上 https ,也不会直接传递密钥。 |
![]() | 42 railgun 2015-09-17 14:30:22 +08:00 json 适合用来描述复杂的数据格式 如果只是简单的数据,用哪个都无所谓 还是要从实际出发,比如有的接口是要传文件的,用 json 就不合适了 |
![]() | 43 FrankFang128 2015-09-17 14:32:50 +08:00 @temberature 支持两种方式的话,就没有问题了呀。 调用方怎么都不会错,怎么叫推给他们。 |
![]() | 44 FrankFang128 2015-09-17 14:39:39 +08:00 楼上说什么 JSON 是事实标准的说法有点问题, application/x-www-form-urlencoded; 也是标准啊。 按 REST 来说,根据 Content-Type 的值为 application/x-www-form-urlencoded 还是 application/json 做下判断就好了。 |
![]() | 45 temberature OP @FrankFang128 我的意思不是把麻烦推给他们,是把分析两种方式的利弊推给了他们;在接口方,我倾向在理想情况把一种实现好,毕竟现实中资源和精力是有限的;同意都是标准的说法,但是事实标准是可能存在的。 |
![]() | 46 jokcy 2015-09-17 15:56:50 +08:00 @morethansean 你可以用 payload 的方式传数据 |
![]() | 47 temberature OP @pandada8 有时候确实会遇到自己难以决定或者双方难以一致的问题,这时候我的态度就先实现一种(直觉有时候也管用),在使用经验增长之后,答案自然就有了。 ps :突然想到“约定大于配置”。 |
![]() | 48 temberature OP @railgun 文件确实特殊;一个项目中应该都有复杂点的数据,统一的约定还是挺重要的吧 |
![]() | 49 temberature OP @gamexg hash 时 json 字符串中的顺序也需要注意吧 |
![]() | 50 temberature OP @jokcy 一直没太明白设计这个的目的 |
![]() | 51 gamexg 2015-09-17 16:50:20 +08:00 @temberature 客户端是对序列化后的字符串签名,服务端是先验证签名后反序列化,所以不涉及 key 顺序的问题。 |
![]() | 52 temberature OP @gamexg 也见过接口的字符串签名算法,其实也可以按 json 这种,不明白为什么要排序:) |
![]() | 53 FrankFang128 2015-09-17 17:34:22 +08:00 我觉得没必要 2 选 1 的,两种同时存在是 OK 的,也是更为常见的。 |
![]() | 54 yield9tk 2015-09-17 17:44:34 +08:00 两种可以同属存在。不同的压缩方式,在 accept 中设置即可 |
![]() | 55 railgun 2015-09-17 17:54:43 +08:00 @temberature 那就 json 吧,适配性好一点,扩展也方便 |
56 hantsy 2015-09-17 17:58:23 +08:00 @gamexg 一些 oAuth2 provider 提供了 JWT 支持, 连接的时候使用, Spring 内置了支持(只需要设置)。其他情况真的没看到签名的使用。国内 X 宝 X 度通篇的 Sign ,除了让 API 看起来像屎一样,如果它的加密方法和顺序被预先知道了,我不觉得是安全的。 如果你想做所有请求还要加密, X509 应该可以了吧。我想只有银行级的安全才会有这种要求。 |
![]() | 57 Geoion 2015-09-17 18:16:12 +08:00 两个尖括号的流量也省。。。。。 |
![]() | 58 temberature OP @Geoion 对于用户量亿级的服务,还是有大差别的吧 |
![]() | 59 jokcy 2015-09-17 18:23:42 +08:00 @temberature content-type 不一样 |
60 hantsy 2015-09-17 20:28:16 +08:00 @temberature 针对 Mobile 原生程序(比如 Android , IOS )的某些场合可以绕开 HTTP ,特别图片等数据量大的东西,使用更底层的协议通讯,效率更高。其它文本类的,全部用 JSON ,所有平台都通用。 其实, REST API 的设计,只要参考 Github API , 或者 Heroku 的 API 就好了。设计好的 API ,从根到底下资源是一个树型结构,如 / 是根, /posts 是 Post 资源集合, /posts/2 是 ID 为 2 的单个资源,/posts/2/comments ,是指 ID 为 2 的 Post 下面的所有 Comments 。如果使用 HAL , 从根开始添加一些必要的 metadata 信息, 下面的所有的资源都应该是可以 Discovery 的,使用 HAL Browser 这样工具是可以可视化整个 API 结构,而不需要借助文档说明。 |
61 morethansean 2015-09-18 09:08:38 +08:00 @jokcy web 单页应用直接 form data 不好么。 |
![]() | 62 jokcy 2015-09-18 09:57:49 +08:00 @morethansean 不是不好,而是根据你们自己的需求自己定义,你这边以 form 格式传后台就以 form 格式接收并转换,用 json 的好处就是如果你的后台用的是类似 node 这样天生支持 json 数据的,那么就无需转换了。 |
![]() | 63 matthewgao 2015-09-19 10:48:20 +08:00 @hantsy 我再补充一下, REST 还要注意状态转移和等幂性 |
![]() | 64 matthewgao 2015-09-19 10:49:53 +08:00 @hantsy 多谢,我之前还没看到任何标准和参考说道到这个是可以的,反倒刻意去回避这个 |