I am trying to deserialize youtube data from the endpoint http://www.youtube.com/feeds/videos.xml?channel_id=UCHnyfMqiRRG1u-2MsSQLbXA
into the Feed
struct in the below Rust
program. It is returning None for the media_group
field in the struct Entry
, even though the raw XML contains information.
NOTE :: PASTE THE http://www.youtube.com/feeds/videos.xml?channel_id=UCHnyfMqiRRG1u-2MsSQLbXA
INTO A BROWSER TO VISUALIZE THE XML BETTER
// youtube_data.rsuse hyper::{Body, Client, Uri};use hyper_tls::HttpsConnector;use serde::Deserialize;use quick_xml::de::{from_str, DeError};use crate::internals::singularity::WidgetError;impl From<DeError> for WidgetError { fn from(err: DeError) -> Self { WidgetError::XmlParse(err.to_string()) }}#[derive(Debug, Deserialize)]#[serde(rename = "feed")]pub struct Feed { id: String, #[serde(rename = "channelId", default)] yt_channel_id: Option<String>, title: String, published: String, #[serde(default)] #[serde(rename = "entry")] entries: Vec<Entry>,}#[derive(Debug, Deserialize)]struct Entry { id: String, title: String, published: String, #[serde(rename = "mediaGroup")] media_group: Option<MediaGroup>,}#[derive(Debug, Deserialize)]struct MediaGroup { #[serde(rename = "mediaTitle")] title: Option<String>, #[serde(rename = "mediaContent")] content: Option<MediaContent>, #[serde(rename = "mediaThumbnail")] thumbnail: Option<MediaThumbnail>, #[serde(rename = "mediaCommunity")] community: Option<MediaCommunity>,}#[derive(Debug, Deserialize)]struct MediaContent { #[serde(rename = "@url")] url: String, #[serde(rename = "@width")] width: u32, #[serde(rename = "@height")] height: u32,}#[derive(Debug, Deserialize)]struct MediaThumbnail { #[serde(rename = "@url")] url: String, #[serde(rename = "@width")] width: u32, #[serde(rename = "@height")] height: u32,}#[derive(Debug, Deserialize)]struct MediaCommunity { #[serde(rename = "mediaStarRating")] star_rating: Option<StarRating>, #[serde(rename = "mediaStatistics")] statistics: Option<Statistics>,}#[derive(Debug, Deserialize)]struct StarRating { #[serde(rename = "@count")] count: u64,}#[derive(Debug, Deserialize)]struct Statistics { #[serde(rename = "@views")] views: u64,}pub async fn get_youtube_vids_for_a_channel(channel_id: String) -> Result<Feed, WidgetError> { let url = format!("https://www.youtube.com/feeds/videos.xml?channel_id={}", channel_id ); let uri: Uri = url.parse().unwrap(); let https = HttpsConnector::new(); let client = Client::builder().build::<_, Body>(https); let res = client.get(uri).await?; let body = hyper::body::to_bytes(res.into_body()).await?; let response_text = String::from_utf8(body.to_vec()) .map_err(|e| WidgetError::Utf8Error(e.to_string()))?; // println!("{:#?}", response_text); let feed: Feed = from_str(&response_text)?; Ok(feed)}
// singularity.rs#[derive(Debug, Error)]pub enum WidgetError { #[error("Hyper error: {0}")] Hyper(#[from] hyper::Error), #[error("No geocoding data found")] NoGeocodingData, #[error("Error in reading HTML file")] NoHtmlToString, #[error("Serde JSON error: {0}")] SerdeJson(#[from] serde_json::Error), #[error("No timezone found")] NoTimeZone, #[error("XML parsing error: {0}")] XmlParse(String), #[error("UTF-8 conversion error: {0}")] Utf8Error(String),}
The dependencies used are
[dependencies]hyper = { version = "0.14", features = ["full"] }hyper-tls = "0.5"regex = "1.10.5"serde = { version = "1.0", features = ["derive"] }thiserror = "1.0.63"quick-xml = { version = "0.37", features = ["serialize"] }
Even though Raw XML contains the data why is it not serializing it properly ??