Skip to main content

jsonld_syntax/
into_json.rs

1use crate::{Container, ContainerKind, ContextEntry, Direction, Keyword, LenientLangTagBuf, Nullable, context, hash::IndexSet};
2use contextual::Contextual;
3
4impl<T: IntoJsonWithContext<N>, N> IntoJsonWithContext<N> for Vec<T> {
5    fn into_json_with(self, context: &N) -> jstrict::Value {
6        jstrict::Value::Array(self.into_iter().map(|item| item.into_json_with(context)).collect())
7    }
8}
9
10impl<T: IntoJsonWithContext<N>, N> IntoJsonWithContext<N> for IndexSet<T> {
11    fn into_json_with(self, context: &N) -> jstrict::Value {
12        jstrict::Value::Array(self.into_iter().map(|item| item.into_json_with(context)).collect())
13    }
14}
15
16/// Values convertible into JSON through a vocabulary.
17pub trait IntoJsonWithContext<N>: Sized {
18    /// Converts this value into JSON, resolving the identifiers it holds
19    /// against the given vocabulary.
20    ///
21    /// This conversion is infallible by design: every identifier is expected
22    /// to resolve in the given context (vocabulary). Passing a vocabulary the
23    /// value was not built against is a caller bug; implementations render
24    /// identifiers that fail to resolve as the literal string
25    /// `"<unresolved iri>"` rather than panicking.
26    fn into_json_with(self, context: &N) -> jstrict::Value;
27}
28
29/// Values convertible into JSON.
30pub trait IntoJson: Sized {
31    /// Converts this value into JSON.
32    fn into_json(self) -> jstrict::Value;
33}
34
35impl<T: IntoJsonWithContext<N>, N> IntoJson for Contextual<T, &N> {
36    fn into_json(self) -> jstrict::Value {
37        T::into_json_with(self.0, self.1)
38    }
39}
40
41impl<T: IntoJsonWithContext<N>, N> IntoJson for Contextual<T, &mut N> {
42    fn into_json(self) -> jstrict::Value {
43        T::into_json_with(self.0, self.1)
44    }
45}
46
47impl IntoJson for bool {
48    fn into_json(self) -> jstrict::Value {
49        jstrict::Value::Boolean(self)
50    }
51}
52
53impl<T: IntoJson> IntoJson for Box<T> {
54    fn into_json(self) -> jstrict::Value {
55        T::into_json(*self)
56    }
57}
58
59impl IntoJson for iri_rs::IriRefBuf {
60    fn into_json(self) -> jstrict::Value {
61        jstrict::Value::String(self.as_str().into())
62    }
63}
64
65impl<T: IntoJson> IntoJson for Nullable<T> {
66    fn into_json(self) -> jstrict::Value {
67        match self {
68            Self::Null => jstrict::Value::Null,
69            Self::Some(other) => T::into_json(other),
70        }
71    }
72}
73
74impl IntoJson for Keyword {
75    fn into_json(self) -> jstrict::Value {
76        jstrict::Value::String(self.into_str().into())
77    }
78}
79
80impl IntoJson for String {
81    fn into_json(self) -> jstrict::Value {
82        jstrict::Value::String(self.into())
83    }
84}
85
86impl IntoJson for LenientLangTagBuf {
87    fn into_json(self) -> jstrict::Value {
88        jstrict::Value::String(self.into_string().into())
89    }
90}
91
92impl IntoJson for Direction {
93    fn into_json(self) -> jstrict::Value {
94        jstrict::Value::String(self.as_str().into())
95    }
96}
97
98impl IntoJson for context::definition::TypeContainer {
99    fn into_json(self) -> jstrict::Value {
100        jstrict::Value::String(self.into_str().into())
101    }
102}
103
104impl IntoJson for context::definition::Type {
105    fn into_json(self) -> jstrict::Value {
106        let mut object = jstrict::Object::new();
107
108        object.insert("@container".into(), self.container.into_json());
109
110        if let Some(protected) = self.protected {
111            object.insert("@protected".into(), protected.into_json());
112        }
113
114        jstrict::Value::Object(object)
115    }
116}
117
118impl IntoJson for context::definition::Version {
119    fn into_json(self) -> jstrict::Value {
120        jstrict::Value::Number(self.into())
121    }
122}
123
124impl IntoJson for context::definition::Vocab {
125    fn into_json(self) -> jstrict::Value {
126        jstrict::Value::String(self.into_string().into())
127    }
128}
129
130impl IntoJson for context::definition::Key {
131    fn into_json(self) -> jstrict::Value {
132        jstrict::Value::String(self.into_string().into())
133    }
134}
135
136impl IntoJson for context::term_definition::Index {
137    fn into_json(self) -> jstrict::Value {
138        jstrict::Value::String(self.into_string().into())
139    }
140}
141
142impl IntoJson for context::term_definition::Nest {
143    fn into_json(self) -> jstrict::Value {
144        jstrict::Value::String(self.into_string().into())
145    }
146}
147
148impl IntoJson for Container {
149    fn into_json(self) -> jstrict::Value {
150        match self {
151            Self::One(c) => ContainerKind::into_json(c),
152            Self::Many(list) => jstrict::Value::Array(list.into_iter().map(IntoJson::into_json).collect()),
153        }
154    }
155}
156
157impl IntoJson for ContainerKind {
158    fn into_json(self) -> jstrict::Value {
159        jstrict::Value::String(self.as_str().into())
160    }
161}
162
163impl IntoJson for context::term_definition::Id {
164    fn into_json(self) -> jstrict::Value {
165        match self {
166            Self::Keyword(k) => Keyword::into_json(k),
167            Self::Term(t) => String::into_json(t),
168        }
169    }
170}
171
172impl IntoJson for context::Context {
173    fn into_json(self) -> jstrict::Value {
174        match self {
175            Self::One(c) => c.into_json(),
176            Self::Many(list) => jstrict::Value::Array(list.into_iter().map(IntoJson::into_json).collect()),
177        }
178    }
179}
180
181impl IntoJson for ContextEntry {
182    fn into_json(self) -> jstrict::Value {
183        match self {
184            Self::Null => jstrict::Value::Null,
185            Self::IriRef(iri) => iri_rs::IriRefBuf::into_json(iri),
186            Self::Definition(def) => context::Definition::into_json(def),
187        }
188    }
189}
190
191impl IntoJson for context::Definition {
192    fn into_json(self) -> jstrict::Value {
193        let mut object = jstrict::Object::new();
194
195        if let Some(base) = self.base {
196            object.insert("@base".into(), base.into_json());
197        }
198
199        if let Some(import) = self.import {
200            object.insert("@import".into(), import.into_json());
201        }
202
203        if let Some(language) = self.language {
204            object.insert("@language".into(), language.into_json());
205        }
206
207        if let Some(direction) = self.direction {
208            object.insert("@direction".into(), direction.into_json());
209        }
210
211        if let Some(propagate) = self.propagate {
212            object.insert("@propagate".into(), propagate.into_json());
213        }
214
215        if let Some(protected) = self.protected {
216            object.insert("@protected".into(), protected.into_json());
217        }
218
219        if let Some(type_) = self.type_ {
220            object.insert("@type".into(), type_.into_json());
221        }
222
223        if let Some(version) = self.version {
224            object.insert("@version".into(), version.into_json());
225        }
226
227        if let Some(vocab) = self.vocab {
228            object.insert("@vocab".into(), vocab.into_json());
229        }
230
231        for (key, binding) in self.bindings {
232            object.insert(key.into_string().into(), binding.into_json());
233        }
234
235        jstrict::Value::Object(object)
236    }
237}
238
239impl IntoJson for context::TermDefinition {
240    fn into_json(self) -> jstrict::Value {
241        match self {
242            Self::Simple(s) => context::term_definition::Simple::into_json(s),
243            Self::Expanded(e) => context::term_definition::Expanded::into_json(*e),
244        }
245    }
246}
247
248impl IntoJson for context::term_definition::Simple {
249    fn into_json(self) -> jstrict::Value {
250        jstrict::Value::String(self.into_string().into())
251    }
252}
253
254impl IntoJson for context::term_definition::Type {
255    fn into_json(self) -> jstrict::Value {
256        jstrict::Value::String(self.into_string().into())
257    }
258}
259
260impl IntoJson for context::term_definition::TypeKeyword {
261    fn into_json(self) -> jstrict::Value {
262        jstrict::Value::String(self.into_str().into())
263    }
264}
265
266impl IntoJson for context::term_definition::Expanded {
267    fn into_json(self) -> jstrict::Value {
268        let mut object = jstrict::Object::new();
269
270        if let Some(id) = self.id {
271            object.insert("@id".into(), id.into_json());
272        }
273
274        if let Some(type_) = self.type_ {
275            object.insert("@type".into(), type_.into_json());
276        }
277
278        if let Some(context) = self.context {
279            object.insert("@context".into(), context.into_json());
280        }
281
282        if let Some(reverse) = self.reverse {
283            object.insert("@reverse".into(), reverse.into_json());
284        }
285
286        if let Some(index) = self.index {
287            object.insert("@index".into(), index.into_json());
288        }
289
290        if let Some(language) = self.language {
291            object.insert("@language".into(), language.into_json());
292        }
293
294        if let Some(direction) = self.direction {
295            object.insert("@direction".into(), direction.into_json());
296        }
297
298        if let Some(container) = self.container {
299            object.insert("@container".into(), container.into_json());
300        }
301
302        if let Some(nest) = self.nest {
303            object.insert("@nest".into(), nest.into_json());
304        }
305
306        if let Some(prefix) = self.prefix {
307            object.insert("@prefix".into(), prefix.into_json());
308        }
309
310        if let Some(propagate) = self.propagate {
311            object.insert("@propagate".into(), propagate.into_json());
312        }
313
314        if let Some(protected) = self.protected {
315            object.insert("@protected".into(), protected.into_json());
316        }
317
318        jstrict::Value::Object(object)
319    }
320}