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()
}