Skip to main content

jsonld_serialization/
lib.rs

1//! Serialization of RDF datasets into JSON-LD.
2//!
3//! Turns an RDF dataset — or any type implementing [`ld_core::LinkedData`],
4//! which includes types deriving it — into a [`jsonld_core::ExpandedDocument`].
5//! This is the inverse of the `to_rdf` direction implemented in
6//! `jsonld-core`.
7//!
8//! Blank nodes are resolved through the interpretation the dataset was built
9//! against, so the same resource seen twice yields one node object rather than
10//! two.
11use std::hash::Hash;
12
13use jsonld_core::{ExpandedDocument, Node, Object};
14
15use ld_core::{LinkedData, LinkedDataResource, LinkedDataSubject};
16use rdfx::{
17    Interpretation,
18    interpretation::{ReverseInterpretation, ReverseLocalInterpretation},
19    vocabulary::Vocabulary,
20};
21
22mod expanded;
23
24use expanded::SerializeExpandedDocument;
25
26pub use expanded::{serialize_node_with, serialize_object_with};
27
28#[derive(Debug, thiserror::Error)]
29/// Error raised while serializing a document.
30pub enum Error {
31    #[error("invalid graph label")]
32    /// Invalid graph label.
33    InvalidGraph,
34
35    #[error("invalid predicate")]
36    /// Invalid predicate.
37    InvalidPredicate,
38
39    #[error("invalid node object")]
40    /// Invalid node object.
41    InvalidNode,
42
43    #[error("reverse properties on lists are not supported")]
44    /// Reverse properties on lists are not supported.
45    ListReverseProperty,
46
47    #[error("included nodes on lists are not supported")]
48    /// Included nodes on lists are not supported.
49    ListInclude,
50}
51
52type DefaultInterpretation = rdfx::generator::LocalGeneratorInterpretation<rdfx::generator::Blank>;
53
54fn default_interpretation() -> DefaultInterpretation {
55    rdfx::generator::LocalGeneratorInterpretation::new(rdfx::generator::Blank::new())
56}
57
58/// Serialize the given Linked-Data value into a JSON-LD document.
59///
60/// # Errors
61///
62/// Returns an error when the value cannot be expressed as a JSON-LD document.
63pub fn serialize(value: &impl LinkedData<DefaultInterpretation>) -> Result<ExpandedDocument, Error> {
64    serialize_with(&mut (), &mut default_interpretation(), value)
65}
66
67/// Serialize the given Linked-Data value into a JSON-LD document using a
68/// custom vocabulary and interpretation.
69///
70/// # Errors
71///
72/// Returns an error when the value cannot be expressed as a JSON-LD document.
73pub fn serialize_with<V, I>(vocabulary: &mut V, interpretation: &mut I, value: &impl LinkedData<I>) -> Result<ExpandedDocument<V::Iri, V::BlankId>, Error>
74where
75    V: Vocabulary + rdfx::vocabulary::VocabularyMut,
76    V::Iri: Clone + Eq + Hash,
77    V::BlankId: Clone + Eq + Hash,
78    I: Interpretation + ReverseInterpretation + ReverseLocalInterpretation,
79{
80    let serializer = SerializeExpandedDocument::new(vocabulary, interpretation);
81
82    value.visit(serializer)
83}
84
85/// Serialize the given Linked-Data value into a JSON-LD object.
86///
87/// # Errors
88///
89/// Returns an error when the value cannot be expressed as a JSON-LD object.
90pub fn serialize_object(value: &(impl LinkedDataSubject<DefaultInterpretation> + LinkedDataResource<DefaultInterpretation>)) -> Result<Object, Error> {
91    serialize_object_with(&mut (), &mut default_interpretation(), value)
92}
93
94/// Serialize the given Linked-Data value into a JSON-LD node object.
95///
96/// # Errors
97///
98/// Returns an error when the value cannot be expressed as a JSON-LD node object.
99pub fn serialize_node(value: &(impl LinkedDataSubject<DefaultInterpretation> + LinkedDataResource<DefaultInterpretation>)) -> Result<Node, Error> {
100    serialize_node_with(&mut (), &mut default_interpretation(), value)
101}