1#[macro_export]
2macro_rules! json_literal {
3 ($ty:ty) => {
4 impl<V: $crate::rdf_types::Vocabulary, I: $crate::rdf_types::Interpretation> $crate::LinkedDataResource<I, V> for $ty {
5 fn interpretation(
6 &self,
7 _vocabulary: &mut V,
8 _interpretation: &mut I,
9 ) -> $crate::ResourceInterpretation<I, V> {
10 use $crate::{rdf_types::Term, CowRdfTerm, RdfLiteral, ResourceInterpretation};
11
12 let mut value = $crate::json_syntax::to_value(self).unwrap();
13 value.canonicalize();
14
15 ResourceInterpretation::Uninterpreted(Some(CowRdfTerm::Owned(Term::Literal(
16 RdfLiteral::Json(value),
17 ))))
18 }
19 }
20
21 impl<V: $crate::rdf_types::Vocabulary, I: $crate::rdf_types::Interpretation> $crate::LinkedDataPredicateObjects<I, V> for $ty {
22 fn visit_objects<S>(&self, mut visitor: S) -> Result<S::Ok, S::Error>
23 where
24 S: $crate::PredicateObjectsVisitor<I, V>,
25 {
26 visitor.object(self)?;
27 visitor.end()
28 }
29 }
30
31 impl<V: $crate::rdf_types::Vocabulary, I: $crate::rdf_types::Interpretation> $crate::LinkedDataDeserializePredicateObjects<I, V> for $ty
32 where
33 V: $crate::rdf_types::Vocabulary,
34 I: $crate::rdf_types::interpretation::ReverseIriInterpretation<Iri = V::Iri> + $crate::rdf_types::interpretation::ReverseLiteralInterpretation<Literal = V::Literal>
35 {
36 fn deserialize_objects_in<'a, D>(
37 vocabulary: &V,
38 interpretation: &I,
39 dataset: &D,
40 graph: Option<&I::Resource>,
41 objects: impl IntoIterator<Item = &'a I::Resource>,
42 context: $crate::Context<I>
43 ) -> Result<Self, $crate::FromLinkedDataError>
44 where
45 I::Resource: 'a,
46 D: $crate::rdf_types::dataset::PatternMatchingDataset<Resource = I::Resource>
47 {
48 let mut objects = objects.into_iter();
49 match objects.next() {
50 Some(object) => {
51 if objects.next().is_none() {
52 <Self as $crate::LinkedDataDeserializeSubject<I, V>>::deserialize_subject_in(vocabulary, interpretation, dataset, graph, object, context)
53 } else {
54 Err($crate::FromLinkedDataError::TooManyValues(
55 context.into_iris(vocabulary, interpretation)
56 ))
57 }
58 }
59 None => {
60 Err($crate::FromLinkedDataError::MissingRequiredValue(
61 context.into_iris(vocabulary, interpretation)
62 ))
63 }
64 }
65 }
66 }
67
68 impl<V: $crate::rdf_types::Vocabulary, I: $crate::rdf_types::Interpretation> $crate::LinkedDataSubject<I, V> for $ty {
69 fn visit_subject<S>(&self, visitor: S) -> Result<S::Ok, S::Error>
70 where
71 S: $crate::SubjectVisitor<I, V>,
72 {
73 visitor.end()
74 }
75 }
76
77 impl<V: $crate::rdf_types::Vocabulary, I: $crate::rdf_types::Interpretation> $crate::LinkedDataDeserializeSubject<I, V> for $ty
78 where
79 V: $crate::rdf_types::Vocabulary,
80 I: $crate::rdf_types::interpretation::ReverseIriInterpretation<Iri = V::Iri> + $crate::rdf_types::interpretation::ReverseLiteralInterpretation<Literal = V::Literal>
81 {
82 fn deserialize_subject_in<D>(
83 vocabulary: &V,
84 interpretation: &I,
85 _dataset: &D,
86 _graph: Option<&I::Resource>,
87 resource: &I::Resource,
88 context: $crate::Context<I>
89 ) -> Result<Self, $crate::FromLinkedDataError>
90 where
91 D: $crate::rdf_types::dataset::PatternMatchingDataset<Resource = I::Resource>
92 {
93 use $crate::rdf_types::LiteralTypeRef;
94
95 let mut literal_ty = None;
96 for l in interpretation.literals_of(resource) {
97 let literal = vocabulary.literal(l).unwrap();
98 match literal.type_ {
99 LiteralTypeRef::Any(ty) => {
100 let ty_iri = vocabulary.iri(ty).unwrap();
101 if ty_iri == $crate::rdf_types::RDF_JSON {
102 use $crate::json_syntax::Parse;
103 let (json, _) = $crate::json_syntax::Value::parse_str(literal.value)
104 .map_err(|_| $crate::FromLinkedDataError::InvalidLiteral(
105 context.into_iris(vocabulary, interpretation)
106 ))?;
107
108 return $crate::json_syntax::from_value(json).map_err(|_| $crate::FromLinkedDataError::InvalidLiteral(
109 context.into_iris(vocabulary, interpretation)
110 ))
111 } else {
112 literal_ty = Some(ty_iri)
113 }
114 }
115 LiteralTypeRef::LangString(_) => {
116 literal_ty = Some($crate::rdf_types::RDF_LANG_STRING)
117 }
118 }
119 }
120
121 match literal_ty {
122 Some(ty) => {
123 Err($crate::FromLinkedDataError::LiteralTypeMismatch {
124 context: context.into_iris(vocabulary, interpretation),
125 expected: Some($crate::rdf_types::RDF_JSON.to_owned()),
126 found: ty.to_owned()
127 })
128 }
129 None => {
130 Err($crate::FromLinkedDataError::ExpectedLiteral(
131 context.into_iris(vocabulary, interpretation)
132 ))
133 }
134 }
135 }
136 }
137 };
138}
139
140#[cfg(test)]
141mod test {
142 #[derive(Debug, serde::Serialize, serde::Deserialize)]
143 struct Test {
144 field: String,
145 }
146
147 json_literal!(Test);
148}