sea-orm
sea-orm copied to clipboard
FromJsonQueryResult should also work with generic types
Description
FromJsonQueryResult
currently doesn't work with generics. This is useful to e. g. wrap a Vec<T>
in a custom type List<T>(Vec<T>)
that implements the required traits to be used in SeaORM.
This is caused by the FromJsonQueryResult
currently ignoring any generics.
This can be fixed with these changes to expand_derive_from_json_query_result
and derive_from_json_query_result
:
- replace all occurances of
impl
withimpl #generics
where#generics
comes from the parsed macro input - replace all occurances of
#ident
with#ident_with_generics
where#ident_with_generics
is theident
followed by the generic paramters with their trait bounds removed - add trait bounds
where #ident_with_generics: Serialize
andwhere #ident_with_generics: DeserializeOwned
where required (see workaround below)
Steps to Reproduce
-
cargo new test-project
-
cd test-project
-
cargo add sea-orm
-
cargo add serde -F derive
-
cargo add serde_json
- Paste this code into
src/main.rs
use sea_orm::{prelude::*, FromJsonQueryResult};
use serde::{Deserialize, Serialize};
[derive(Clone, Debug, Default, PartialEq, Deserialize, Serialize, FromJsonQueryResult)]
#[serde(transparent)]
pub struct List<T>(pub Vec<T>);
Expected Behavior
compiles without errors
Actual Behavior
error[E0107]: missing generics for struct `List`
--> src/main.rs:16:12
|
16 | pub struct List<T>(pub Vec<T>);
| ^^^^ expected 1 generic argument
|
note: struct defined here, with 1 generic parameter: `T`
--> src/main.rs:16:12
|
16 | pub struct List<T>(pub Vec<T>);
| ^^^^ -
help: add missing generic argument
|
16 | pub struct List<T><T>(pub Vec<T>);
| +++
Reproduces How Often
Is it always reproducible? -> Yes
Workarounds
manually implement the derived traits:
[derive(Clone, Debug, Default, PartialEq, Deserialize, Serialize)]
#[serde(transparent)]
pub struct List<T>(pub Vec<T>);
impl<T> sea_orm::TryGetableFromJson for List<T> where for<'de> T: Deserialize<'de> {}
impl<T> std::convert::From<List<T>> for sea_orm::Value
where
List<T>: Serialize,
{
fn from(source: List<T>) -> Self {
sea_orm::Value::Json(
serde_json::to_value(&source)
.ok()
.map(|s| std::boxed::Box::new(s)),
)
}
}
impl<T> sea_orm::sea_query::ValueType for List<T>
where
List<T>: DeserializeOwned,
{
fn try_from(v: sea_orm::Value) -> Result<Self, sea_orm::sea_query::ValueTypeErr> {
match v {
sea_orm::Value::Json(Some(json)) => {
Ok(serde_json::from_value(*json).map_err(|_| sea_orm::sea_query::ValueTypeErr)?)
}
_ => Err(sea_orm::sea_query::ValueTypeErr),
}
}
fn type_name() -> String {
stringify!(#ident).to_owned()
}
fn array_type() -> sea_orm::sea_query::ArrayType {
sea_orm::sea_query::ArrayType::Json
}
fn column_type() -> sea_orm::sea_query::ColumnType {
sea_orm::sea_query::ColumnType::Json
}
}
impl<T> sea_orm::sea_query::Nullable for List<T> {
fn null() -> sea_orm::Value {
sea_orm::Value::Json(None)
}
}
Reproducible Example
[derive(Clone, Debug, Default, PartialEq, Deserialize, Serialize, FromJsonQueryResult)]
#[serde(transparent)]
pub struct List<T>(pub Vec<T>);
Versions
❯ cargo tree | grep sea-
├── sea-orm v0.12.10
│ ├── sea-orm-macros v0.12.10 (proc-macro)
│ │ ├── sea-bae v0.2.0 (proc-macro)
│ ├── sea-query v0.30.6
@nitn3lav Will you be creating a PR for this as well?