用于访问多个资源的API的REST设计

时间:2012-06-04 21:41:20

标签: rest

想象一个API,它会为zap2it TV listings.

等电视广告资源应用返回JSON数据

它基本上是一个电视频道列表,每个频道都是当前及以后的节目。目前,我有一个返回所有频道GET /channels的API。但是,需要为该数据中的每个通道添加当前显示的节目。我正在考虑添加一个新的API GET /channels/on_now,以区别于当前的API。 我希望对新API有所了解,我不想为每个频道单独调用,需要为所有频道返回show-on-now数据。这是一个良好的REST API设计?

当前GET /channels JSON数据

[
   "channel": {
      "channelName": "KRON4",
    },
   "channel": {
      "channelName": "KTOV5",
    },
   ...
]

下面的新API GET /channels/on_now的预期JSON数据

[
  {
   "channel": {
      "channelName": "KRON4",
    },
    "on_now": {
      "startTime": "2012-06-04T11:30:00",
      "endTime": "2012-06-04T12:00:00",
      "shortDescription": "Latest local, statewide & national news events, along with sports & weather.",
      "shortTitle": "4:30am Newscast"
    }
  },
  {
   "channel": {
      "channelName": "KTOV5",
    },
    "on_now": {
      "startTime": "2012-06-04T11:30:00",
      "endTime": "2012-06-04T12:30:00",
      "shortDescription": "Local morning news and weather report",
      "shortTitle": "Morning Newscast"
    }
  },
  ...next channel...
]

5 个答案:

答案 0 :(得分:3)

我建议专注于内容,而不是网址。

示例:您有一个入口点'/'。这是API中唯一的URL。得到它就像

一样
{
    "channels" : {
        "href" : "path.to/channels"
        },
    "programs" : {
        "href" : "path.to/programs"
        }
}

要检索频道列表,您需要获取相应的网址 - 之前您不需要知道 - 并获取,例如:

[
    {
        "name" : "BBC",
        "id" : 452,
        "href" : "path.to/channels/452"
    },
    {
        "name" : "FOO",
        "id"   : 112,
        "href" : "path.to/channels/112"
    }
] 

有关BBC的详细信息,请在提供的网址上获取:

{
    "name" : "BBC",
    "id" : 452,
    "self" : "path.to/channels/452",
    "live_url" : "link.to.bbc.cast",
    "whatever" : "bar",
    "current" : "path.to/channels/452/current",
    "program" : "path.to/channels/452/program"
}

等等。 URL是即时发现的;你可以随时修改它们。是什么让你的API成为内容:你必须同意客户关于返回的内容(字段,类型,......)。 您最后调用上面的“当前”URL以获取有关当前程序的信息。

请阅读此处了解更多信息:http://kellabyte.com/2011/09/04/clarifying-rest/

OP评论后编辑:

您可以引入'embed'参数以限制请求数量:

GET path.to/channels/452?embed=current

将返回:

{
    "name" : "BBC",
    "id" : 452,
    "self" : "path.to/channels/452",
    "live_url" : "link.to.bbc.cast",
    "whatever" : "bar",
    "current" : {
        "self" : "path.to/channels/452/current",
        "name" : "Morning Show",
        "start_time" : "(datetime here)",
        "end_time"   : "(datetime here)",
        "next"       : "whatever.comes.ne/xt"
        },
    "program" : "path.to/channels/452/program"
}

答案 1 :(得分:2)

你问:

这是一个很好的REST API设计吗?

,是。

与已回答的其他人相反,您可以自由定义任何您想要的资源,只要它代表名词。这包括与时间相关的服务,例如“现在在电视上播放什么”或者在例如“< city>”中的当前天气。这些服务资源与表示节目或频道的更多静态资源一样有效。

但是我会更改URI。 /channels看起来像集合资源URI。我希望它的子节点是频道,例如/channels/kron4(你可以使用任何唯一的字符串,而不是jsut ID来识别实例资源)。
因此,/channels/on_now看起来很奇怪。它看起来像一个名为“on_now”的频道。虽然没有什么可以阻止您使用它,但它可能会与 称为“On Now”的频道冲突! 我只会使用/on_now作为您的URI。 /channels/kron4/on_now显然也适用于单个频道的响应。

答案 2 :(得分:1)

/Channels -----------------------> Get All Channels
/Channels/bbc  ------------------> Get BBC Channel
/Channels/bbc/Shows -------------> Get All shows in BBC
/Channels/bbc/Shows/Baseball ----> Get the show called "Baseball", in bbc channel
/Channels/bbc/Shows/current -----> Get the Current show running, in bbc channel

假设您没有(并且不会)为您的任何频道播放名为Current的节目! :)。

答案 3 :(得分:1)

只需附上上述答案:

/Channels/bbc/Shows/time/now -----> Get all the show played on BBC now
/Channels/bbc/Shows/time/2011-03-27T03:00:00.000+02:00 -----> Get all the show played on BBC  on 2011-03-27T03:00:00.000+02:00 .

这是更具可扩展性的,您不必担心任何名为current的节目。

编辑: 如果您可以通过此处获得api-doc访问权限,那么您可以做出这样的好事({3}}

根据我的说法,需要更多的数据,api就像这样: ?// EPG时间=安培;开始= 0&安培;极限= 1&安培;持续时间=

这将定义一个通用api,以根据时间和持续时间获取基于位置的tv_listing信息。结果将在给定时间跨度内发生的频道列表之间的所有节目中分页。

答案 4 :(得分:1)

我不是API专家,但我认为你应该考虑回归的内容而不是放置资源的“看起来有意义”。

一种解决方案是将on_now视为资源。

所以你的api将是:

/channels (all channels)
/channels/{channel-id} (the {channel-id} channel - could be bbc and can have a collection of shows)
/channels/{channel-id}/shows (shows of channel-id)
/channels/{channel-id}/shows?filter=on_now (you are filtering a result, so i guess it's better to use query string, as if you were doing a query)

然后你想要返回现在的内容,这不是频道的属性,而是自身的资源。那么如何实现呢?

/on_now/ (return a collection of on_now objects, which may be anything, channels, shows, whatever)
/on_now/?channel={channel-id} (this is a filter of the list by channel-id, you are just narrowing the list)

所以不是/channels/{channel-id}/shows?filter=on_now/on_now/?channel={channel-id}相同?

实际上,

在第一个uri中,您将获得由on_now过滤的节目。 在第二个中,您将获得on_nows(可以是任何表示,而不仅仅是一个节目),按频道过滤。

为什么我认为on_now应该被视为资源,为什么它很重要?

当您将此资源分开时,您现在可以对资源进行不同的表示。您还具有更大的灵活性和无碰撞。让我们说明天你想要在on_now中显示另一个不在任何频道上的'节目',这很容易就可以完成,而其他方法只需要在频道上。 您也可以稍后按不同的标准过滤on_now,因为它们是独立的对象。

你也可以这样做:

/on_now/{on_now_id} 

将提供当前节目的详细信息,例如当它开始时,它何时结束以及将位置放置到/shows/{show-id},以便您可以在它现在不再使用之后到达它。

然而,我认为最佳解决方案是将节目作为频道的无连接资源。 但最重要的是,我认为你还应该问自己,你是否希望节目成为频道的基础......

是什么暗示
  

I don't want to make individual call for each channel, the show-on-now data needs to be returned for all channels

一部分。

这让我觉得节目不应该在/channels/路径内。

那是因为如果你只是回归节目,另一种方法是/shows/?filter=on_now

你可以:

/shows/?filters=on_now&channel=bbc

我喜欢将资源视为我回归的“事物”,而不仅仅是关系的标准思维。图中的底层对于属性是很好的,对于“其他事物”的收集不太确定。

按照相同的示例,我宁愿使用/channels/{channel-id}/program代替/channels/{channel-id}/shows