cdx_core/extensions/semantic/
jsonld.rs1use serde::{Deserialize, Serialize};
4
5use super::BibliographyEntry;
6
7#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
9#[serde(rename_all = "camelCase")]
10pub struct JsonLdMetadata {
11 #[serde(rename = "@context")]
13 pub context: Vec<String>,
14
15 #[serde(rename = "@graph", default, skip_serializing_if = "Vec::is_empty")]
17 pub graph: Vec<serde_json::Value>,
18}
19
20impl JsonLdMetadata {
21 #[must_use]
23 pub fn new() -> Self {
24 Self {
25 context: vec!["https://schema.org".to_string()],
26 graph: Vec::new(),
27 }
28 }
29
30 #[must_use]
32 pub fn with_context(mut self, context: impl Into<String>) -> Self {
33 self.context.push(context.into());
34 self
35 }
36
37 pub fn add_node(&mut self, node: serde_json::Value) {
39 self.graph.push(node);
40 }
41
42 #[must_use]
44 pub fn creative_work(name: impl Into<String>, author: impl Into<String>) -> serde_json::Value {
45 serde_json::json!({
46 "@type": "CreativeWork",
47 "name": name.into(),
48 "author": {
49 "@type": "Person",
50 "name": author.into()
51 }
52 })
53 }
54
55 #[must_use]
57 pub fn scholarly_article(entry: &BibliographyEntry) -> serde_json::Value {
58 let mut article = serde_json::json!({
59 "@type": "ScholarlyArticle",
60 "name": entry.title
61 });
62
63 if !entry.authors.is_empty() {
64 let authors: Vec<_> = entry
65 .authors
66 .iter()
67 .map(|a| {
68 serde_json::json!({
69 "@type": "Person",
70 "name": a.display_name()
71 })
72 })
73 .collect();
74 article["author"] = serde_json::json!(authors);
75 }
76
77 if let Some(date) = &entry.issued {
78 article["datePublished"] = serde_json::json!(date.to_string());
79 }
80
81 if let Some(doi) = &entry.doi {
82 article["identifier"] = serde_json::json!({
83 "@type": "PropertyValue",
84 "propertyID": "DOI",
85 "value": doi
86 });
87 }
88
89 if let Some(journal) = &entry.container_title {
90 article["isPartOf"] = serde_json::json!({
91 "@type": "Periodical",
92 "name": journal
93 });
94 }
95
96 article
97 }
98}
99
100impl Default for JsonLdMetadata {
101 fn default() -> Self {
102 Self::new()
103 }
104}