use std::{any::type_name, ops::RangeInclusive, sync::Arc};
use itertools::Itertools;
use mzcv::SynonymScope;
use serde::de::DeserializeOwned;
use serde_json::Value;
use context_error::*;
use crate::{
ontology::Ontology,
sequence::{GnoComposition, GnoSubsumption},
};
pub trait ParseJson: Sized {
fn from_json_value(value: Value) -> Result<Self, BoxedError<'static, BasicKind>>;
fn from_json(value: &str) -> Result<Self, BoxedError<'static, BasicKind>> {
let value = serde_json::from_str::<Value>(value).map_err(|err| {
BoxedError::new(
BasicKind::Error,
format!("Invalid JSON (for {})", type_name::<Self>()),
err.to_string(),
Context::show(value.to_string()),
)
})?;
Self::from_json_value(value)
}
}
#[expect(clippy::needless_pass_by_value)]
pub fn use_serde<T: DeserializeOwned>(value: Value) -> Result<T, BoxedError<'static, BasicKind>> {
serde_json::from_value(value.clone()).map_err(|err| {
BoxedError::new(
BasicKind::Error,
format!("Could not parse JSON into {}", type_name::<T>()),
err.to_string(),
Context::show(value.to_string()),
)
})
}
macro_rules! use_serde {
($ty:ty) => {
impl ParseJson for $ty {
fn from_json_value(value: Value) -> Result<Self, BoxedError<'static, BasicKind>> {
use_serde(value)
}
}
};
}
use_serde!(bool);
use_serde!(String);
use_serde!(Box<str>);
use_serde!(usize);
use_serde!(u128);
use_serde!(u64);
use_serde!(u32);
use_serde!(u16);
use_serde!(u8);
use_serde!(isize);
use_serde!(i128);
use_serde!(i64);
use_serde!(i32);
use_serde!(i16);
use_serde!(i8);
use_serde!(f64);
use_serde!(f32);
use_serde!(Ontology);
use_serde!(SynonymScope);
use_serde!(GnoComposition);
use_serde!(GnoSubsumption);
impl<T: DeserializeOwned> ParseJson for RangeInclusive<T> {
fn from_json_value(value: Value) -> Result<Self, BoxedError<'static, BasicKind>> {
use_serde(value)
}
}
impl<T: ParseJson> ParseJson for Option<T> {
fn from_json_value(value: Value) -> Result<Self, BoxedError<'static, BasicKind>> {
if value == Value::Null {
Ok(None)
} else {
T::from_json_value(value).map(Some)
}
}
}
impl<T: ParseJson> ParseJson for Arc<T> {
fn from_json_value(value: Value) -> Result<Self, BoxedError<'static, BasicKind>> {
T::from_json_value(value).map(Self::new)
}
}
impl<T: ParseJson> ParseJson for thin_vec::ThinVec<T> {
fn from_json_value(value: Value) -> Result<Self, BoxedError<'static, BasicKind>> {
if let Value::Array(arr) = value {
arr.into_iter()
.map(|element| T::from_json_value(element))
.collect()
} else {
Err(BoxedError::new(
BasicKind::Error,
"Invalid JSON",
format!(
"The JSON has to be a sequence to parse a list of {}",
type_name::<T>()
),
Context::show(value.to_string()),
))
}
}
}
impl<T: ParseJson> ParseJson for Vec<T> {
fn from_json_value(value: Value) -> Result<Self, BoxedError<'static, BasicKind>> {
if let Value::Array(arr) = value {
arr.into_iter()
.map(|element| T::from_json_value(element))
.collect()
} else {
Err(BoxedError::new(
BasicKind::Error,
"Invalid JSON",
format!(
"The JSON has to be a sequence to parse a list of {}",
type_name::<T>()
),
Context::show(value.to_string()),
))
}
}
}
impl<A: ParseJson, B: ParseJson> ParseJson for (A, B) {
fn from_json_value(value: Value) -> Result<Self, BoxedError<'static, BasicKind>> {
if let Value::Array(mut arr) = value {
if arr.len() == 2 {
let b = B::from_json_value(arr.pop().unwrap())?;
let a = A::from_json_value(arr.pop().unwrap())?;
Ok((a, b))
} else {
Err(BoxedError::new(
BasicKind::Error,
"Invalid JSON",
"The JSON is a sequence but does not have 2 children",
Context::show(arr.iter().join(",")),
))
}
} else {
Err(BoxedError::new(
BasicKind::Error,
"Invalid JSON",
format!(
"The JSON has to be a sequence to parse a ({}, {})",
type_name::<A>(),
type_name::<B>(),
),
Context::show(value.to_string()),
))
}
}
}
impl<A: ParseJson, B: ParseJson, C: ParseJson> ParseJson for (A, B, C) {
fn from_json_value(value: Value) -> Result<Self, BoxedError<'static, BasicKind>> {
if let Value::Array(mut arr) = value {
if arr.len() == 3 {
let c = C::from_json_value(arr.pop().unwrap())?;
let b = B::from_json_value(arr.pop().unwrap())?;
let a = A::from_json_value(arr.pop().unwrap())?;
Ok((a, b, c))
} else {
Err(BoxedError::new(
BasicKind::Error,
"Invalid JSON",
"The JSON is a sequence but does not have 3 children",
Context::show(arr.iter().join(",")),
))
}
} else {
Err(BoxedError::new(
BasicKind::Error,
"Invalid JSON",
format!(
"The JSON has to be a sequence to parse a ({}, {}, {})",
type_name::<A>(),
type_name::<B>(),
type_name::<C>(),
),
Context::show(value.to_string()),
))
}
}
}
impl<A: ParseJson, B: ParseJson, C: ParseJson, D: ParseJson> ParseJson for (A, B, C, D) {
fn from_json_value(value: Value) -> Result<Self, BoxedError<'static, BasicKind>> {
if let Value::Array(mut arr) = value {
if arr.len() == 4 {
let d = D::from_json_value(arr.pop().unwrap())?;
let c = C::from_json_value(arr.pop().unwrap())?;
let b = B::from_json_value(arr.pop().unwrap())?;
let a = A::from_json_value(arr.pop().unwrap())?;
Ok((a, b, c, d))
} else {
Err(BoxedError::new(
BasicKind::Error,
"Invalid JSON",
"The JSON is a sequence but does not have 4 children",
Context::show(arr.iter().join(",")),
))
}
} else {
Err(BoxedError::new(
BasicKind::Error,
"Invalid JSON",
format!(
"The JSON has to be a sequence to parse a ({}, {}, {}, {})",
type_name::<A>(),
type_name::<B>(),
type_name::<C>(),
type_name::<D>(),
),
Context::show(value.to_string()),
))
}
}
}