pubmed_parser/europe_pmc/
references.rs

1//! Europe PMC `references` endpoint response parsing.
2
3use serde::{Deserialize, Serialize};
4
5use crate::error::Result;
6
7use super::models::EuropePmcReference;
8
9/// Parsed response from the Europe PMC `references` endpoint (one page).
10#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
11#[serde(from = "RawReferencesResponse")]
12pub struct EuropePmcReferenceList {
13    /// Total number of references for the article (across all pages).
14    pub hit_count: u64,
15    /// The references on this page.
16    pub references: Vec<EuropePmcReference>,
17}
18
19#[derive(Deserialize)]
20#[serde(rename_all = "camelCase")]
21struct RawReferencesResponse {
22    #[serde(default)]
23    hit_count: u64,
24    #[serde(default)]
25    reference_list: RawReferenceList,
26}
27
28#[derive(Deserialize, Default)]
29struct RawReferenceList {
30    #[serde(default)]
31    reference: Vec<EuropePmcReference>,
32}
33
34impl From<RawReferencesResponse> for EuropePmcReferenceList {
35    fn from(raw: RawReferencesResponse) -> Self {
36        Self {
37            hit_count: raw.hit_count,
38            references: raw.reference_list.reference,
39        }
40    }
41}
42
43/// Parse a Europe PMC `references` JSON response.
44pub fn parse_references_response(json: &str) -> Result<EuropePmcReferenceList> {
45    Ok(serde_json::from_str(json)?)
46}
47
48#[cfg(test)]
49mod tests {
50    use super::*;
51
52    #[test]
53    fn test_parse_references() {
54        let json = r#"{
55            "hitCount": 2,
56            "referenceList": {
57                "reference": [
58                    {
59                        "id": 12345,
60                        "source": "MED",
61                        "citationType": "JOURNAL ARTICLE",
62                        "title": "Cited work one",
63                        "authorString": "Doe J.",
64                        "journalAbbreviation": "Nature",
65                        "pubYear": 2010,
66                        "volume": "5",
67                        "issue": "2",
68                        "pageInfo": "100-110",
69                        "pmid": "12345",
70                        "doi": "10.1/abc"
71                    },
72                    {
73                        "title": "Unmatched reference",
74                        "pubYear": 1999
75                    }
76                ]
77            }
78        }"#;
79
80        let resp = parse_references_response(json).unwrap();
81        assert_eq!(resp.hit_count, 2);
82        assert_eq!(resp.references.len(), 2);
83        // pubYear arrives as a JSON number but is normalized to a string.
84        assert_eq!(resp.references[0].pub_year.as_deref(), Some("2010"));
85        assert_eq!(resp.references[0].id.as_deref(), Some("12345"));
86        assert_eq!(resp.references[0].pmid.as_deref(), Some("12345"));
87        assert_eq!(resp.references[1].pub_year.as_deref(), Some("1999"));
88        assert!(resp.references[1].id.is_none());
89    }
90}