V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
jasonyang9
V2EX  ›  PHP

REST API 中,同一个参数多个值,正确的传递姿势是怎样的?

  •  
  •   jasonyang9 · 2018-09-13 15:40:31 +08:00 · 9435 次点击
    这是一个创建于 2044 天前的主题,其中的信息可能已经有所发展或是发生改变。

    比如要获取 2 本书的信息:

    GET http://server/books?id=1001&id=1002
    GET http://server/books?id=1001,1002
    GET http://server/books/1001/1002           这个肯定不对了
    

    当然用 POST 配合 JSON 值过去应该是不符合语义的。

    所以正确的姿势是怎样的?服务器端又应该如何获取这些值?

    41 条回复    2018-09-26 16:45:51 +08:00
    syh
        1
    syh  
       2018-09-13 15:54:28 +08:00
    试下这样 http://server/books?id=1001_1002
    mnssbe
        2
    mnssbe  
       2018-09-13 15:55:10 +08:00
    id 放个 json
    Mutoo
        3
    Mutoo  
       2018-09-13 15:55:55 +08:00   ❤️ 1
    ?ids[]=1001&ids[]=1002
    linxl
        4
    linxl  
       2018-09-13 15:56:02 +08:00   ❤️ 1
    ?id[]=1&id[]=2
    l12ab
        5
    l12ab  
       2018-09-13 15:56:02 +08:00 via iPhone
    id[]=1001,1002
    ChoateYao
        6
    ChoateYao  
       2018-09-13 15:56:25 +08:00   ❤️ 1
    如果是 PHP 的话,直接使用 id[]=1&id[]=2 即可。
    l12ab
        7
    l12ab  
       2018-09-13 15:56:52 +08:00 via iPhone   ❤️ 1
    不好意思,打错了,正确的见 3 楼 4 楼
    chinvo
        8
    chinvo  
       2018-09-13 15:58:04 +08:00 via iPhone
    符合 http 的用数组,或者用逗号分隔
    tanszhe
        9
    tanszhe  
       2018-09-13 15:59:29 +08:00
    ids=[1,2,3,4,5,34,……]
    broadliyn
        10
    broadliyn  
       2018-09-13 16:00:17 +08:00   ❤️ 1
    ids=1,2,3,4 不就好了。
    Restful Api 只是一种 Api 风格,不是强制规范。你完全可以选择性选择自己觉得有用的建议风格。
    没必要奉为圭臬。
    Mutoo
        11
    Mutoo  
       2018-09-13 16:01:29 +08:00   ❤️ 1
    @Mutoo 这种写法的 querystring,PHP 可以直接支持,但并没有出现在任何的 RFC 规范中,其它语言的后端需要自行解析。
    gouflv
        12
    gouflv  
       2018-09-13 16:02:31 +08:00 via iPhone
    GET http://server/books/1001,1002
    fighterlyt
        13
    fighterlyt  
       2018-09-13 16:07:29 +08:00
    url 长度是有限的,而参数是无限的,所以出现在 URL 中的批量参数,都是有局限的
    gaius
        14
    gaius  
       2018-09-13 16:10:44 +08:00   ❤️ 1
    前两种就是 int[]接收
    stzz
        15
    stzz  
       2018-09-13 16:12:27 +08:00   ❤️ 2
    我来个绝对 restful 的方法,
    请求两次
    GuryYu
        16
    GuryYu  
       2018-09-13 16:22:13 +08:00   ❤️ 5
    POST http://server/books/list
    Body 里面用 JSON 传过滤参数
    可以理解成创建一个 books 的临时列表资源, 列表的过滤参数来自 BODY, 并直接返回该资源
    ylcc
        17
    ylcc  
       2018-09-13 16:25:20 +08:00
    三个字,随便弄,只要你的后端能解析
    fighterlyt
        18
    fighterlyt  
       2018-09-13 16:41:19 +08:00
    @GuryYu 看了这个多回复,只有你的说法还是比较合理的,其他都完全不考虑 URL 长度问题
    vicvinc
        19
    vicvinc  
       2018-09-13 16:47:15 +08:00
    /books?include=author&book[]=1001,1002
    vicvinc
        20
    vicvinc  
       2018-09-13 16:48:09 +08:00
    @l12ab 正解
    90safe
        21
    90safe  
       2018-09-13 16:49:06 +08:00
    无论是 POST 还是 GET,都可以用:id[]=1&id[]=2 这样的类型传递。也可以:id=1001,1002 然后接收端分割成数组。
    jasonyang9
        22
    jasonyang9  
    OP
       2018-09-13 16:52:02 +08:00
    多谢各位。我再捣鼓捣鼓
    zhzer
        23
    zhzer  
       2018-09-13 17:02:56 +08:00 via Android
    随便选个分隔符不就完事?
    isayme
        24
    isayme  
       2018-09-13 17:12:30 +08:00
    有的服务端支持 id=1001&id=1002, 有的支持 id[]=1001&id[]=1002, 也有的都支持.
    主要是看你们服务端的支持情况.
    http://httpbin.org/get?a=1&a=2&b[]=3&b[]=4
    https://httpbin.isayme.org/anything?a=1&a=2&b[]=3&b[]=4

    或者直接改用 POST 方法?
    fighterlyt
        25
    fighterlyt  
       2018-09-13 17:24:32 +08:00
    @jasonyang9 别听那伙人瞎比比,URL 长度的限制必须考虑,所以最安全的方法就是 POST
    wunonglin
        26
    wunonglin  
       2018-09-13 17:48:38 +08:00
    ?id=1001,1002
    jowan
        27
    jowan  
       2018-09-13 17:55:14 +08:00
    rogwan
        28
    rogwan  
       2018-09-13 18:05:07 +08:00 via Android
    一般的做法是逗号分隔
    SorcererXW
        29
    SorcererXW  
       2018-09-13 21:19:31 +08:00
    一般来说用逗号分隔问题不大, 比如 stackexchange 的 api 设计: https://api.stackexchange.com/docs/answers-by-ids
    也可以考虑 http batch requests, 可以参考看看 facebook 的 api: https://developers.facebook.com/docs/graph-api/making-multiple-requests
    jingniao
        30
    jingniao  
       2018-09-13 21:33:03 +08:00 via Android
    一直是逗号分隔
    Raymon111111
        31
    Raymon111111  
       2018-09-13 21:36:23 +08:00
    就是 list 啊
    Leammin
        32
    Leammin  
       2018-09-13 23:37:05 +08:00 via Android
    @GuryYu 老哥你解决了我困扰已久的问题!
    Leammin
        33
    Leammin  
       2018-09-13 23:47:44 +08:00 via Android
    @GuryYu 不过 delete 要怎么办
    freakxx
        34
    freakxx  
       2018-09-14 00:03:03 +08:00
    python -- django

    GET http://server/books?id=1001,1002

    id = "1001, 1002"
    id = id.split(",")

    >>> ['1001', ' 1002']
    skinny
        35
    skinny  
       2018-09-14 07:33:00 +08:00
    @Leammin 你都用了 RESTFUL,难道还用 POST 删除? DELETE 请求被你吃了?
    corningsun
        36
    corningsun  
       2018-09-14 09:10:01 +08:00
    Swagger UI 自动生成的是 第一种
    第二种 URL 长度明显更短

    后端 Java Spring 的话,第一种和第二种都是支持的。
    oongxx
        37
    oongxx  
       2018-09-14 10:00:40 +08:00
    如果你的 API 用了 OData 规范,那就用 http://host/service/Products?$filter=Name in ('Milk', 'Cheese')

    https://stackoverflow.com/questions/7745231/odata-where-id-in-list-query
    wizardoz
        38
    wizardoz  
       2018-09-14 10:13:53 +08:00
    我想知道为啥会出现要用两个 id 来取两本书这种需求?
    id 自然不是随便来的,比如 mike 收藏的两本书,那就用
    http://server/books?favor_by=mike
    来过滤啊。
    JamesC
        39
    JamesC  
       2018-09-14 12:24:48 +08:00
    个人的做法是 /api/resources/(1,3,5,7)
    其实重点在于做好 API 接收解析,id 之间分隔的规范.
    直接获取是不现实的.如何编写符合 Restful 原则的规范才重要.
    又或者 /api/resources?ids=1,3,5,7 也是可以的,路径要清晰,意义明显.
    ps:既然选择了 Restful 的设计思路就尽量符合规范.
    Leammin
        40
    Leammin  
       2018-09-14 19:41:19 +08:00 via Android
    @skinny ?我说的就是 delete 啊,我意思是批量删除要怎么操作。
    yc8332
        41
    yc8332  
       2018-09-26 16:45:51 +08:00
    只能传字符串啊。。。至于形式,看你喜欢啊
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3282 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 31ms · UTC 12:21 · PVG 20:21 · LAX 05:21 · JFK 08:21
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.