json-ld 0.22.0

JSON-LD implementation
Documentation
use json_syntax::{JsonNumberBuf, JsonPrint, JsonValue};
use linked_data::{LinkedDataSerializer, SerializeLinkedData, ser::SerializeLinkedDataWith};
use rdf_syntax::Iri;
use rdf_syntax::{Literal, RDF_JSON, Term};
use xsd_types::{
	XSD_BOOLEAN, XSD_DOUBLE, XSD_INTEGER, XSD_STRING, XsdBoolean, XsdDouble, XsdFromStr,
};

use crate::JsonLdLenient;
use crate::{JsonLdValue, object::value::JsonLdLiteralType};

use super::super::RdfSerializationOptions;

impl SerializeLinkedDataWith<RdfSerializationOptions> for JsonLdValue {
	fn serialize_rdf_with<S>(
		&self,
		_opts: RdfSerializationOptions,
		mut serializer: S,
		_: Option<&Term>,
	) -> Result<S::Ok, S::Error>
	where
		S: LinkedDataSerializer<Term>,
	{
		let literal = match self {
			Self::Literal(lit) => {
				if lit.is_json() {
					Literal::new(
						lit.value.canonicalized().compact_print().to_string(),
						RDF_JSON,
					)
				} else {
					let ty = match &lit.type_ {
						Some(JsonLdLiteralType::Iri(iri)) => iri.as_iri(),
						_ => match &lit.value {
							JsonValue::Null => XSD_STRING,
							JsonValue::Boolean(_) => XSD_BOOLEAN,
							JsonValue::Number(n) => {
								let n = n.trimmed();
								if n.has_decimal_point() || n.has_exponent() {
									XSD_DOUBLE
								} else {
									XSD_INTEGER
								}
							}
							JsonValue::String(_) => XSD_STRING,
							_ => XSD_STRING,
						},
					};

					match &lit.value {
						JsonValue::Null => Literal::new("null", ty),
						JsonValue::Boolean(b) => Literal::new(XsdBoolean(*b).to_string(), ty),
						JsonValue::Number(n) => Literal::new(canonical_number(n, ty), ty),
						JsonValue::String(s) => Literal::new(s.as_str(), ty),
						other => {
							Literal::new(other.canonicalized().compact_print().to_string(), ty)
						}
					}
				}
			}
			Self::LangString(s) => match s.language() {
				Some(lang) => match lang {
					JsonLdLenient::Valid(tag) => Literal::new(s.as_str(), tag),
					JsonLdLenient::Invalid(_) => return serializer.end(),
				},
				None => Literal::new(s.as_str(), XSD_STRING),
			},
		};

		serializer.serialize_resource(Some(Term::literal(literal)))?;
		serializer.end()
	}
}

impl SerializeLinkedData for JsonLdValue {
	fn serialize_rdf<S>(&self, serializer: S, graph: Option<&Term>) -> Result<S::Ok, S::Error>
	where
		S: LinkedDataSerializer<Term>,
	{
		self.serialize_rdf_with(RdfSerializationOptions::default(), serializer, graph)
	}
}

fn canonical_number(n: &JsonNumberBuf, ty: &Iri) -> String {
	let n = n.trimmed();

	if (ty == XSD_DOUBLE || n.has_decimal_point() || n.has_exponent())
		&& let Ok(d) = XsdDouble::xsd_from_str(n)
	{
		return d.to_string();
	}

	n.to_string()
}