Skip to main content

json_ld/algorithms/deserialization/object/
value.rs

1use json_syntax::{JsonNumberBuf, JsonPrint, JsonValue};
2use linked_data::{LinkedDataSerializer, SerializeLinkedData, ser::SerializeLinkedDataWith};
3use rdf_syntax::Iri;
4use rdf_syntax::{Literal, RDF_JSON, Term};
5use xsd_types::{
6	XSD_BOOLEAN, XSD_DOUBLE, XSD_INTEGER, XSD_STRING, XsdBoolean, XsdDouble, XsdFromStr,
7};
8
9use crate::JsonLdLenient;
10use crate::{JsonLdValue, object::value::JsonLdLiteralType};
11
12use super::super::RdfSerializationOptions;
13
14impl SerializeLinkedDataWith<RdfSerializationOptions> for JsonLdValue {
15	fn serialize_rdf_with<S>(
16		&self,
17		_opts: RdfSerializationOptions,
18		mut serializer: S,
19		_: Option<&Term>,
20	) -> Result<S::Ok, S::Error>
21	where
22		S: LinkedDataSerializer<Term>,
23	{
24		let literal = match self {
25			Self::Literal(lit) => {
26				if lit.is_json() {
27					Literal::new(
28						lit.value.canonicalized().compact_print().to_string(),
29						RDF_JSON,
30					)
31				} else {
32					let ty = match &lit.type_ {
33						Some(JsonLdLiteralType::Iri(iri)) => iri.as_iri(),
34						_ => match &lit.value {
35							JsonValue::Null => XSD_STRING,
36							JsonValue::Boolean(_) => XSD_BOOLEAN,
37							JsonValue::Number(n) => {
38								let n = n.trimmed();
39								if n.has_decimal_point() || n.has_exponent() {
40									XSD_DOUBLE
41								} else {
42									XSD_INTEGER
43								}
44							}
45							JsonValue::String(_) => XSD_STRING,
46							_ => XSD_STRING,
47						},
48					};
49
50					match &lit.value {
51						JsonValue::Null => Literal::new("null", ty),
52						JsonValue::Boolean(b) => Literal::new(XsdBoolean(*b).to_string(), ty),
53						JsonValue::Number(n) => Literal::new(canonical_number(n, ty), ty),
54						JsonValue::String(s) => Literal::new(s.as_str(), ty),
55						other => {
56							Literal::new(other.canonicalized().compact_print().to_string(), ty)
57						}
58					}
59				}
60			}
61			Self::LangString(s) => match s.language() {
62				Some(lang) => match lang {
63					JsonLdLenient::Valid(tag) => Literal::new(s.as_str(), tag),
64					JsonLdLenient::Invalid(_) => return serializer.end(),
65				},
66				None => Literal::new(s.as_str(), XSD_STRING),
67			},
68		};
69
70		serializer.serialize_resource(Some(Term::literal(literal)))?;
71		serializer.end()
72	}
73}
74
75impl SerializeLinkedData for JsonLdValue {
76	fn serialize_rdf<S>(&self, serializer: S, graph: Option<&Term>) -> Result<S::Ok, S::Error>
77	where
78		S: LinkedDataSerializer<Term>,
79	{
80		self.serialize_rdf_with(RdfSerializationOptions::default(), serializer, graph)
81	}
82}
83
84fn canonical_number(n: &JsonNumberBuf, ty: &Iri) -> String {
85	let n = n.trimmed();
86
87	if (ty == XSD_DOUBLE || n.has_decimal_point() || n.has_exponent())
88		&& let Ok(d) = XsdDouble::xsd_from_str(n)
89	{
90		return d.to_string();
91	}
92
93	n.to_string()
94}