前言

现状和思路

#[derive(Default, Serialize, Deserialize, Debug, Clone, PartialEq, Properties)]
pub struct Cve {
  pub id: String,
  pub year: i32,
  pub assigner: String,
  pub description: Vec<nvd_cves::v4::Description>,
  pub severity: String,
  pub metrics: nvd_cves::impact::ImpactMetrics,
  pub weaknesses: Vec<nvd_cves::v4::Weaknesses>,
  pub configurations: Vec<nvd_cves::v4::configurations::Node>,
  pub references: Vec<nvd_cves::v4::Reference>,
  pub created_at: NaiveDateTime,
  pub updated_at: NaiveDateTime,
}
#[cfg_attr(feature = "openapi", derive(ToSchema))]
#[derive(Queryable, Serialize, Deserialize, Identifiable, Debug, PartialEq)]
#[diesel(table_name = cves)]
pub struct Cve {
  pub id: String,
  pub year: i32,
  pub assigner: String,
  pub description: Value,
  pub severity: String,
  pub metrics: Value,
  pub weaknesses: Value,
  pub configurations: Value,
  pub references: Value,
  pub created_at: NaiveDateTime,
  pub updated_at: NaiveDateTime,
}

解决方案

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "db", derive(AsExpression, FromSqlRow), diesel(sql_type = Json))]
#[serde(transparent)]
pub struct AnyValue<T: Clone>
where
  T: Clone,
{
  inner: T,
}
impl<T: Default + for<'de> serde::Deserialize<'de> + Clone> AnyValue<T> {
  pub fn new(t: T) -> Self {
    Self { inner: t }
  }
}

impl<T: Default + Clone> Deref for AnyValue<T> {
  type Target = T;

  fn deref(&self) -> &Self::Target {
    &self.inner
  }
}

impl<T: Default + Clone> DerefMut for AnyValue<T> {
  fn deref_mut(&mut self) -> &mut Self::Target {
    &mut self.inner
  }
}
#[cfg(feature = "db")]
impl<T: Debug + Clone, DB: Backend> FromSql<Json, DB> for AnyValue<T>
where
  serde_json::Value: FromSql<Json, DB>,
  T: DeserializeOwned,
{
  fn from_sql(bytes: DB::RawValue<'_>) -> deserialize::Result<Self> {
    let value = <serde_json::Value as FromSql<Json, DB>>::from_sql(bytes)?;
    Ok(serde_json::from_value(value)?)
  }
}

#[cfg(feature = "db")]
impl<T: Debug + Clone> ToSql<Json, DB> for AnyValue<T>
where
  serde_json::Value: ToSql<Json, DB>,
  T: Serialize,
{
  fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, DB>) -> serialize::Result {
    let value = serde_json::to_value(&self.inner)?;
    <serde_json::Value as ToSql<Json, DB>>::to_sql(&value, &mut out.reborrow())
  }
}

使用自定义类型

#[cfg_attr(feature = "openapi", derive(ToSchema))]
#[cfg_attr(feature = "db", derive(Queryable, Identifiable), diesel(table_name = cves))]
#[cfg_attr(feature = "yew", derive(Properties))]
#[derive(Default, Serialize, Clone, Deserialize, Debug, PartialEq)]
pub struct Cve {
  pub id: String,
  pub year: i32,
  pub assigner: String,
  pub description: AnyValue<Vec<nvd_cves::v4::Description>>,
  pub severity: String,
  pub metrics: AnyValue<nvd_cves::impact::ImpactMetrics>,
  pub weaknesses: AnyValue<Vec<nvd_cves::v4::Weaknesses>>,
  pub configurations: AnyValue<Vec<nvd_cves::v4::configurations::Node>>,
  pub references: AnyValue<Vec<nvd_cves::v4::Reference>>,
  pub created_at: NaiveDateTime,
  pub updated_at: NaiveDateTime,
}
<div class="card-header">
{self.description(&cve.description)}
	</div>
	  {self.cvss(cve.clone())}
	  {self.references(&cve.references)}
	  {self.weaknesses(&cve.weaknesses)}
	  {self.exploit(cve.id)}
	  {self.configurations(&cve.configurations)}
	  <Comments/>
	<div class="card-body">
</div>

自动序列化UUID

#[cfg_attr(feature = "openapi", derive(ToSchema))]
#[derive(Default, Serialize, Deserialize, Debug, Clone, PartialEq)]
#[cfg_attr(feature = "db", derive(Queryable, Identifiable, Selectable), diesel(table_name = vendors))]
#[cfg_attr(feature = "yew", derive(Properties))]
pub struct Vendor {
  #[serde(with = "uuid_serde")]
  pub id: Vec<u8>,
  pub official: u8,
  pub name: String,
  pub description: Option<String>,
  pub meta: AnyValue<MetaData>,
  pub updated_at: NaiveDateTime,
  pub created_at: NaiveDateTime,
}
pub mod uuid_serde {
  use serde::{Deserializer, Serializer};

  pub fn serialize<S: Serializer>(v: &[u8], s: S) -> Result<S::Ok, S::Error> {
    match uuid::Uuid::from_slice(v) {
      Ok(u) => uuid::serde::compact::serialize(&u, s),
      Err(e) => Err(serde::ser::Error::custom(e)),
    }
  }

  pub fn deserialize<'de, D: Deserializer<'de>>(d: D) -> Result<Vec<u8>, D::Error> {
    match uuid::serde::compact::deserialize(d) {
      Ok(u) => Ok(u.as_bytes().to_vec()),
      Err(e) => Err(serde::de::Error::custom(e)),
    }
  }
}

参考

Powered by Kali-Team