json_ld_serialization/expanded/
object.rs

1use std::hash::Hash;
2
3use json_ld_core::{
4	object::{
5		node::{Included, Multiset, Properties, ReverseProperties},
6		Graph, List,
7	},
8	rdf::{RDF_FIRST, RDF_REST, RDF_TYPE},
9	Indexed, IndexedObject, Node, Object,
10};
11use linked_data::{CowRdfTerm, LinkedDataResource};
12use rdf_types::{
13	interpretation::{
14		ReverseBlankIdInterpretation, ReverseIriInterpretation, ReverseLiteralInterpretation,
15	},
16	vocabulary::IriVocabularyMut,
17	Id, Interpretation, Term, Vocabulary,
18};
19
20use crate::Error;
21
22use super::{
23	graph::SerializeGraph,
24	list::{SerializeListFirst, SerializeListRest},
25	node::{into_type_value, is_iri, SerializeNode},
26	property::{SerializeProperty, SerializeReverseProperty},
27	serialize_node_with,
28	value::literal_to_value,
29};
30
31/// Serialize the given Linked-Data value into a JSON-LD object using a
32/// custom vocabulary and interpretation.
33pub fn serialize_object_with<I, V, T>(
34	vocabulary: &mut V,
35	interpretation: &mut I,
36	value: &T,
37) -> Result<Object<V::Iri, V::BlankId>, Error>
38where
39	V: Vocabulary + IriVocabularyMut,
40	V::Iri: Clone + Eq + Hash,
41	V::BlankId: Clone + Eq + Hash,
42	I: ReverseIriInterpretation<Iri = V::Iri>
43		+ ReverseBlankIdInterpretation<BlankId = V::BlankId>
44		+ ReverseLiteralInterpretation<Literal = V::Literal>,
45	T: ?Sized + LinkedDataResource<I, V> + linked_data::LinkedDataSubject<I, V>,
46{
47	match value
48		.lexical_representation(vocabulary, interpretation)
49		.map(CowRdfTerm::into_owned)
50	{
51		Some(Term::Literal(lit)) => {
52			let value = literal_to_value(vocabulary, lit);
53			Ok(Object::Value(value))
54		}
55		Some(Term::Id(id)) => {
56			let serializer = SerializeNode::new(
57				vocabulary,
58				interpretation,
59				Some(json_ld_core::Id::Valid(id)),
60			);
61
62			Ok(Object::node(value.visit_subject(serializer)?))
63		}
64		None => {
65			let serializer = SerializeObject::new(vocabulary, interpretation);
66
67			value.visit_subject(serializer)
68		}
69	}
70}
71
72pub struct SerializeObject<'a, I, V: Vocabulary> {
73	vocabulary: &'a mut V,
74	interpretation: &'a mut I,
75	types: Vec<json_ld_core::Id<V::Iri, V::BlankId>>,
76	properties: Properties<V::Iri, V::BlankId>,
77	reverse_properties: ReverseProperties<V::Iri, V::BlankId>,
78	included: Included<V::Iri, V::BlankId>,
79	graph: Option<Graph<V::Iri, V::BlankId>>,
80	first: Option<Object<V::Iri, V::BlankId>>,
81	rest: Option<Vec<IndexedObject<V::Iri, V::BlankId>>>,
82}
83
84impl<'a, I, V: Vocabulary> SerializeObject<'a, I, V> {
85	pub fn new(vocabulary: &'a mut V, interpretation: &'a mut I) -> Self {
86		Self {
87			vocabulary,
88			interpretation,
89			types: Vec::new(),
90			properties: Properties::new(),
91			reverse_properties: ReverseProperties::new(),
92			included: Included::new(),
93			graph: None,
94			first: None,
95			rest: None,
96		}
97	}
98}
99
100impl<'a, I: Interpretation, V: Vocabulary> linked_data::SubjectVisitor<I, V>
101	for SerializeObject<'a, I, V>
102where
103	V: IriVocabularyMut,
104	V::Iri: Clone + Eq + Hash,
105	V::BlankId: Clone + Eq + Hash,
106	I: ReverseIriInterpretation<Iri = V::Iri>
107		+ ReverseBlankIdInterpretation<BlankId = V::BlankId>
108		+ ReverseLiteralInterpretation<Literal = V::Literal>,
109{
110	type Ok = Object<V::Iri, V::BlankId>;
111	type Error = Error;
112
113	fn predicate<L, T>(&mut self, predicate: &L, value: &T) -> Result<(), Self::Error>
114	where
115		L: ?Sized + LinkedDataResource<I, V>,
116		T: ?Sized + linked_data::LinkedDataPredicateObjects<I, V>,
117	{
118		let prop = match predicate
119			.lexical_representation(self.vocabulary, self.interpretation)
120			.map(CowRdfTerm::into_owned)
121		{
122			Some(Term::Id(id)) => {
123				if let Id::Iri(iri) = &id {
124					let iri = self.vocabulary.iri(iri).unwrap();
125					if iri == RDF_FIRST {
126						let serializer =
127							SerializeListFirst::new(self.vocabulary, self.interpretation);
128						self.first = value.visit_objects(serializer)?;
129					} else if iri == RDF_REST {
130						let serializer =
131							SerializeListRest::new(self.vocabulary, self.interpretation);
132						self.rest = Some(value.visit_objects(serializer)?);
133					}
134				}
135
136				json_ld_core::Id::Valid(id)
137			}
138			_ => return Err(Error::InvalidPredicate),
139		};
140
141		let serializer = SerializeProperty::new(self.vocabulary, self.interpretation);
142
143		let objects = value.visit_objects(serializer)?;
144
145		if is_iri(self.vocabulary, &prop, RDF_TYPE) {
146			let mut non_iri_objects = Multiset::new();
147
148			for obj in objects {
149				match into_type_value(obj) {
150					Ok(ty) => self.types.push(ty),
151					Err(obj) => {
152						non_iri_objects.insert(obj);
153					}
154				}
155			}
156
157			if !non_iri_objects.is_empty() {
158				self.properties.set(prop, non_iri_objects);
159			}
160		} else {
161			self.properties.set(prop, objects);
162		}
163
164		Ok(())
165	}
166
167	fn reverse_predicate<L, T>(&mut self, predicate: &L, value: &T) -> Result<(), Self::Error>
168	where
169		L: ?Sized + LinkedDataResource<I, V>,
170		T: ?Sized + linked_data::LinkedDataPredicateObjects<I, V>,
171	{
172		let prop = match predicate
173			.lexical_representation(self.vocabulary, self.interpretation)
174			.map(CowRdfTerm::into_owned)
175		{
176			Some(Term::Id(id)) => json_ld_core::Id::Valid(id),
177			_ => return Err(Error::InvalidPredicate),
178		};
179
180		let serializer = SerializeReverseProperty::new(self.vocabulary, self.interpretation);
181
182		let objects = value.visit_objects(serializer)?;
183		self.reverse_properties.set(prop, objects);
184
185		Ok(())
186	}
187
188	fn include<T>(&mut self, value: &T) -> Result<(), Self::Error>
189	where
190		T: ?Sized + LinkedDataResource<I, V> + linked_data::LinkedDataSubject<I, V>,
191	{
192		let node = serialize_node_with(self.vocabulary, self.interpretation, value)?;
193		self.included.insert(Indexed::none(node));
194		Ok(())
195	}
196
197	fn graph<T>(&mut self, value: &T) -> Result<(), Self::Error>
198	where
199		T: ?Sized + linked_data::LinkedDataGraph<I, V>,
200	{
201		let serializer = SerializeGraph::new(self.vocabulary, self.interpretation);
202		self.graph = Some(value.visit_graph(serializer)?);
203		Ok(())
204	}
205
206	fn end(mut self) -> Result<Self::Ok, Self::Error> {
207		if self.first.is_some()
208			&& self.rest.is_some()
209			&& self.types.is_empty()
210			&& self.properties.is_empty()
211			&& self.graph.is_none()
212		{
213			let mut items = self.rest.unwrap();
214			items.push(Indexed::none(self.first.unwrap()));
215			items.reverse();
216			Ok(Object::List(List::new(items)))
217		} else {
218			if let Some(item) = self.first {
219				let iri = self.vocabulary.insert(RDF_FIRST);
220				self.properties
221					.insert(json_ld_core::Id::Valid(Id::Iri(iri)), Indexed::none(item))
222			}
223
224			if let Some(rest) = self.rest {
225				let iri = self.vocabulary.insert(RDF_REST);
226				self.properties.insert(
227					json_ld_core::Id::Valid(Id::Iri(iri)),
228					Indexed::none(Object::List(List::new(rest))),
229				)
230			}
231
232			let mut node = Node::new();
233
234			if !self.types.is_empty() {
235				node.types = Some(self.types)
236			}
237
238			*node.properties_mut() = self.properties;
239
240			if !self.reverse_properties.is_empty() {
241				node.set_reverse_properties(Some(self.reverse_properties));
242			}
243
244			if !self.included.is_empty() {
245				node.set_included(Some(self.included));
246			}
247
248			node.graph = self.graph;
249
250			Ok(Object::node(node))
251		}
252	}
253}