【发布时间】:2020-12-11 00:18:26
【问题描述】:
根据谷歌的YouTube v3 API reference documentation for the properties of a video resource,有一个名为liveStreamingDetails的JSON对象应该有以下字段:
actualStartTimeactualEndTimescheduledStartTimescheduledEndTimeconcurrentViewersactiveLiveChatId
我已经根据这种结构准备了我的对象,但是当我尝试反序列化来自视频 API 的实际 JSON snippet 响应时,我收到了以下异常:
JsonSerializationException: Error converting value "none" to type 'A1ITF.API+YouTube+LiveStreamDetails'. Path 'items[0].snippet.liveBroadcastContent', line 46, position 38.ArgumentException: Could not cast or convert from System.String to A1ITF.API+YouTube+LiveStreamDetails.
查看来自 API 的 JSON 响应,我完全理解错误。这是我收到的 JSON 响应(为简洁起见已编辑):
{
"kind": "youtube#videoListResponse",
"etag": "MR2hZ6pif1LwlWdiOvdZ_4m7vDI",
"items": [
{
"kind": "youtube#video",
"etag": "hfbATXrQ1iQB2yrckDCv-dn0iiI",
"id": "skSK9lUvqjY",
"snippet": {
"publishedAt": "2020-08-14T19:00:15Z",
"channelId": "UCZGYJFUizSax-yElQaFDp5Q",
"title": "Leia, Princess of Alderaan | The Star Wars Show Book Club",
"description": <LONG DESCRIPTION TEXT>,
"thumbnails": {<THUMBNAIL OBJECTS>},
"channelTitle": "Star Wars",
"tags": [<SEVERAL TAGS>],
"categoryId": "24",
"liveBroadcastContent": "none",
"localized": {
"title": "Leia, Princess of Alderaan | The Star Wars Show Book Club",
"description": <LONG DESCRIPTION TEXT>
},
"defaultAudioLanguage": "en-US"
}
}
],
"pageInfo": {
"totalResults": 1,
"resultsPerPage": 1
}
}
异常原因很明确:liveBroadcastContent 字段的值是单个字符串 ("none")。它不是上面文档中定义的对象。根据文档,我期待
"liveBroadcastContent":
{
"actualStartTime": <ISO 8601 datetime VALUE>,
"actualEndTime": <ISO 8601 datetime VALUE>,
"scheduledStartTime": <ISO 8601 datetime VALUE>,
"scheduledEndTime": <ISO 8601 datetime VALUE>,
"concurrentViewers": <unsigned long VALUE>,
"activeLiveChatId": <string VALUE>
},
或者,如果没有任何信息可以填充 liveBroadcastContent 字段
"liveBroadcastContent":
{
"actualStartTime": null,
"actualEndTime": null,
"scheduledStartTime": null,
"scheduledEndTime": null,
"concurrentViewers": null,
"activeLiveChatId": ""
},
甚至
"liveBroadcastContent": {},
或只是完全省略该属性与我实际接收的内容不匹配接收
"liveBroadcastContent": "none",
我实际上一直在努力寻找一种有效的方法来有条件地反序列化这个元素,但似乎无法让它简单地返回 Nothing 来表示 API 返回的内容(这是另一个再次提出问题,但我仍在研究希望实现这一目标的方法)。
不过,我最初的测试是针对“常规”视频(不是实际的直播),所以我想我会检查一个已知的直播视频。我查看了我的 YouTube 通知,发现了几个专业/半专业的 YouTube 频道,它们最近有直播,并选择了一个进行测试。但是,此视频的 JSON也缺少结构化的 liveStreamingDetails 对象(只有 "none" 的值)。认为这可能是“侥幸”,我检查了一些其他视频,这些视频在我的 YouTube 通知中被指定为直播,所有视频都显示了完全相同的结果。
如果我将对象中此字段的定义更改为简单的String,则所有内容都会毫无例外地反序列化,并且我得到一个(大部分)完全填充的对象。但是,我实际上喜欢为我的应用程序提供这些信息 - 至少要知道视频是否是/曾经是现场直播 - 但 "none" 显然不会告诉我很多。所以,虽然我正在努力使我的对象正确并有条件地反序列化这个字段的值(我在输入这个时想出了一些想法),我想知道是否有人知道这个字段是否真的实现了?我基本上是在旋转我的轮子,试图让已经被弃用的东西工作,这是打算在未来实施的东西,还是我只是完全密集并且错过了一些明显的东西(一个明确而明显的可能性)?
编辑(由接受的答案解决)
根据接受的答案,我 非常密集。我错误地猜测 liveBroadcastContent 字段(在snippet 对象中)与 liveStreamingDetails 对象相同(items 集合的一部分)。如果我彻底准确地阅读了文档,我会看到前者被定义为(emphasis mine):
string表明视频是否为即将到来的/活跃的直播。或者,如果视频不是即将播出/活跃直播,则为“无”。
此属性的有效值为:
livenoneupcoming
(在我所有的测试中显示为"none"的原因是直播已经结束了)
后者被定义为(包含在接受的答案中):
object
liveStreamingDetails对象包含有关实时视频广播的元数据。如果视频是即将播出、正在直播或已完成的直播,则该对象只会出现在video资源中。
此外,我的 API 请求存在缺陷。当我调用正确的端点时,我实际上并没有请求填充liveStreamingDetails 对象所需的信息。当我应该请求 part=snippet,liveStreamingDetails 时,我才请求 part=snippet。
示例 API 请求:准备好的(非现场)视频
https://www.googleapis.com/youtube/v3/videos?id=skSK9lUvqjY&part=snippet,liveStreamingDetails&key={API_KEY}
返回(为简洁起见编辑)
{
"kind": "youtube#videoListResponse",
"etag": "MR2hZ6pif1LwlWdiOvdZ_4m7vDI",
"items": [
{
"kind": "youtube#video",
"etag": "hfbATXrQ1iQB2yrckDCv-dn0iiI",
"id": "skSK9lUvqjY",
"snippet": {
"publishedAt": "2020-08-14T19:00:15Z",
"channelId": "UCZGYJFUizSax-yElQaFDp5Q",
"title": "Leia, Princess of Alderaan | The Star Wars Show Book Club",
"description": <LONG DESCRIPTION TEXT>,
"thumbnails": {<THUMBNAIL OBJECTS>},
"channelTitle": "Star Wars",
"tags": [<TAGS>],
"categoryId": "24",
"liveBroadcastContent": "none",
"localized": {
"title": "Leia, Princess of Alderaan | The Star Wars Show Book Club",
"description": <LONG DESCRIPTION TEXT>
},
"defaultAudioLanguage": "en-US"
}
}
],
"pageInfo": {
"totalResults": 1,
"resultsPerPage": 1
}
}
示例 API 请求:实时流广播
https://www.googleapis.com/youtube/v3/videos?id=RX4vy_M-NS8&part=snippet,liveStreamingDetails&key={API_KEY}
返回(为简洁起见编辑)
{
"kind": "youtube#videoListResponse",
"etag": "Aq44bdQmbZxoLEp0SOJh4xW0PSE",
"items": [
{
"kind": "youtube#video",
"etag": "9TVc3oB01vQME2QsvEJcaRueEqc",
"id": "RX4vy_M-NS8",
"snippet": {
"publishedAt": "2020-08-20T18:50:20Z",
"channelId": "UCRTQL0CmZjHlvPy5nLZ1Gfg",
"title": "Starting a new character in Star Wars: The Old Republic [Live Stream Recorded on August 20, 2020]",
"description": <LONG DESCRIPTION TEXT>,
"thumbnails": {<THUMBNAIL OBJECTS>},
"channelTitle": "HelloGreedo",
"tags": [<TAGS>],
"categoryId": "1",
"liveBroadcastContent": "none",
"localized": {
"title": "Starting a new character in Star Wars: The Old Republic [Live Stream Recorded on August 20, 2020]",
"description": <LONG DESCRIPTION TEXT>
}
},
"liveStreamingDetails": {
"actualStartTime": "2020-08-20T17:04:45Z",
"actualEndTime": "2020-08-20T18:41:23Z"
}
}
],
"pageInfo": {
"totalResults": 1,
"resultsPerPage": 1
}
}
在更正我的 API 请求并将适当的属性添加到我在代码中准备好的对象之后,我想要的一切都完全按照预期/期望的方式完成。
【问题讨论】:
标签: json youtube json.net youtube-data-api