oxirs_core/format/
jsonld.rs1use super::error::SerializeResult;
7use super::error::{ParseResult, RdfParseError};
8use super::format::JsonLdProfileSet;
9use super::serializer::QuadSerializer;
10use crate::jsonld;
11use crate::model::{Quad, QuadRef};
12use std::io::{Read, Write};
13
14pub struct JsonLdParser {
20 inner: jsonld::JsonLdParser,
21 profile: JsonLdProfileSet,
22}
23
24impl JsonLdParser {
25 pub fn new() -> Self {
27 Self {
28 inner: jsonld::JsonLdParser::new(),
29 profile: JsonLdProfileSet::empty(),
30 }
31 }
32
33 pub fn with_profile(mut self, profile: JsonLdProfileSet) -> Self {
35 self.profile = profile.clone();
36 let jsonld_profile_set = profile.to_jsonld_profile_set();
38 self.inner = self.inner.with_profile(jsonld_profile_set);
39 self
40 }
41
42 pub fn with_base_iri(mut self, base_iri: impl Into<String>) -> Result<Self, RdfParseError> {
44 let base_iri_str = base_iri.into();
45 self.inner = self
46 .inner
47 .with_base_iri(base_iri_str.clone())
48 .map_err(|e| RdfParseError::syntax(format!("Invalid base IRI: {e}")))?;
49 Ok(self)
50 }
51
52 pub fn lenient(mut self) -> Self {
54 self.inner = self.inner.lenient();
55 self
56 }
57
58 pub fn parse_reader<R: Read>(&self, reader: R) -> ParseResult<Vec<Quad>> {
60 self.inner
62 .clone()
63 .for_reader(reader)
64 .collect::<Result<Vec<_>, _>>()
65 .map_err(|e| RdfParseError::syntax(format!("JSON-LD parse error: {e}")))
66 }
67
68 pub fn parse_slice(&self, slice: &[u8]) -> ParseResult<Vec<Quad>> {
70 self.inner
72 .clone()
73 .for_slice(slice)
74 .collect::<Result<Vec<_>, _>>()
75 .map_err(|e| RdfParseError::syntax(format!("JSON-LD parse error: {e}")))
76 }
77
78 pub fn parse_str(&self, input: &str) -> ParseResult<Vec<Quad>> {
80 self.parse_slice(input.as_bytes())
81 }
82
83 pub fn profile(&self) -> &JsonLdProfileSet {
85 &self.profile
86 }
87}
88
89impl Default for JsonLdParser {
90 fn default() -> Self {
91 Self::new()
92 }
93}
94
95#[derive(Clone)]
100pub struct JsonLdSerializer {
101 inner: jsonld::JsonLdSerializer,
102 profile: JsonLdProfileSet,
103}
104
105impl JsonLdSerializer {
106 pub fn new() -> Self {
108 Self {
109 inner: jsonld::JsonLdSerializer::new(),
110 profile: JsonLdProfileSet::empty(),
111 }
112 }
113
114 pub fn with_profile(mut self, profile: JsonLdProfileSet) -> Self {
116 self.profile = profile;
117 self
118 }
119
120 pub fn with_prefix(
122 mut self,
123 prefix: impl Into<String>,
124 iri: impl Into<String>,
125 ) -> Result<Self, RdfParseError> {
126 self.inner = self
127 .inner
128 .with_prefix(prefix, iri)
129 .map_err(|e| RdfParseError::syntax(format!("Invalid prefix IRI: {e}")))?;
130 Ok(self)
131 }
132
133 pub fn with_base_iri(mut self, base_iri: impl Into<String>) -> Result<Self, RdfParseError> {
135 self.inner = self
136 .inner
137 .with_base_iri(base_iri)
138 .map_err(|e| RdfParseError::syntax(format!("Invalid base IRI: {e}")))?;
139 Ok(self)
140 }
141
142 pub fn pretty(self) -> Self {
147 self
149 }
150
151 pub fn for_writer<W: Write>(self, writer: W) -> WriterJsonLdSerializer<W> {
153 WriterJsonLdSerializer::new(writer, self)
154 }
155
156 pub fn serialize_to_string(&self, quads: &[Quad]) -> SerializeResult<String> {
158 let mut buffer = Vec::new();
159 {
160 let mut serializer = self.clone().for_writer(&mut buffer);
161 for quad in quads {
162 serializer.serialize_quad(quad.as_ref())?;
163 }
164 serializer.finish()?;
165 }
166 String::from_utf8(buffer)
167 .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))
168 }
169
170 pub fn profile(&self) -> &JsonLdProfileSet {
172 &self.profile
173 }
174}
175
176impl Default for JsonLdSerializer {
177 fn default() -> Self {
178 Self::new()
179 }
180}
181
182pub struct WriterJsonLdSerializer<W: Write> {
186 inner: jsonld::WriterJsonLdSerializer<W>,
187}
188
189impl<W: Write> WriterJsonLdSerializer<W> {
190 pub fn new(writer: W, config: JsonLdSerializer) -> Self {
192 Self {
193 inner: config.inner.for_writer(writer),
194 }
195 }
196
197 pub fn serialize_quad(&mut self, quad: QuadRef<'_>) -> SerializeResult<()> {
199 self.inner
200 .serialize_quad(quad)
201 .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))
202 }
203
204 pub fn finish(self) -> SerializeResult<W> {
206 Box::new(self.inner)
207 .finish()
208 .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))
209 }
210}
211
212impl<W: Write> QuadSerializer<W> for WriterJsonLdSerializer<W> {
213 fn serialize_quad(&mut self, quad: QuadRef<'_>) -> SerializeResult<()> {
214 self.serialize_quad(quad)
215 }
216
217 fn finish(self: Box<Self>) -> SerializeResult<W> {
218 (*self).finish()
219 }
220}
221
222pub mod context {
227 pub use crate::jsonld::{JsonLdLoadDocumentOptions, JsonLdRemoteDocument};
229}
230
231#[cfg(test)]
232mod tests {
233 use super::*;
234 use crate::format::format::{JsonLdProfile, JsonLdProfileSet};
235 use crate::model::*;
236 use crate::vocab::rdf;
237
238 #[test]
239 fn test_jsonld_parser_creation() {
240 let parser = JsonLdParser::new();
241 assert!(parser.profile().profiles().is_empty());
242 }
243
244 #[test]
245 fn test_jsonld_parser_configuration() {
246 let profile = JsonLdProfileSet::from_profile(JsonLdProfile::Expanded);
247
248 let parser = JsonLdParser::new()
249 .with_profile(profile.clone())
250 .with_base_iri("http://example.org/")
251 .expect("operation should succeed");
252
253 assert_eq!(parser.profile(), &profile);
254 }
255
256 #[test]
257 fn test_jsonld_serializer_creation() {
258 let serializer = JsonLdSerializer::new();
259 assert!(serializer.profile().profiles().is_empty());
260 }
261
262 #[test]
263 fn test_jsonld_serializer_configuration() {
264 let profile = JsonLdProfileSet::from_profile(JsonLdProfile::Compacted);
265
266 let serializer = JsonLdSerializer::new()
267 .with_profile(profile.clone())
268 .with_prefix("schema", "http://schema.org/")
269 .expect("operation should succeed")
270 .with_base_iri("http://example.org/")
271 .expect("operation should succeed");
272
273 assert_eq!(serializer.profile(), &profile);
274 }
275
276 #[test]
277 fn test_empty_json_parsing() {
278 let parser = JsonLdParser::new();
279 let result = parser.parse_str("{}");
280 assert!(result.is_ok());
281 }
283
284 #[test]
285 fn test_invalid_json_parsing() {
286 let parser = JsonLdParser::new();
287 let result = parser.parse_str("invalid json");
288 assert!(result.is_err());
289 }
290
291 #[test]
292 fn test_jsonld_roundtrip() {
293 let subject = NamedNode::new("http://example.org/subject").expect("valid IRI");
295 let predicate = rdf::TYPE.clone();
296 let object = NamedNode::new("http://example.org/Type").expect("valid IRI");
297 let quad = Quad::new(subject, predicate, object, GraphName::DefaultGraph);
298
299 let serializer = JsonLdSerializer::new()
301 .with_prefix("ex", "http://example.org/")
302 .expect("operation should succeed");
303 let json_ld = serializer.serialize_to_string(std::slice::from_ref(&quad));
304 assert!(json_ld.is_ok());
305
306 let parser = JsonLdParser::new();
308 let parsed_quads = parser.parse_str(&json_ld.expect("JSON-LD should be valid"));
309 assert!(parsed_quads.is_ok());
310
311 let quads = parsed_quads.expect("quad parsing should succeed");
313 assert!(!quads.is_empty());
314 }
315}