Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FromJsonQueryResult should also work with generic types #2049

Open
nitn3lav opened this issue Jan 3, 2024 · 1 comment
Open

FromJsonQueryResult should also work with generic types #2049

nitn3lav opened this issue Jan 3, 2024 · 1 comment

Comments

@nitn3lav
Copy link

nitn3lav commented Jan 3, 2024

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 with impl #generics where #generics comes from the parsed macro input
  • replace all occurances of #ident with #ident_with_generics where #ident_with_generics is the ident followed by the generic paramters with their trait bounds removed
  • add trait bounds where #ident_with_generics: Serialize and where #ident_with_generics: DeserializeOwned where required (see workaround below)

Steps to Reproduce

  1. cargo new test-project
  2. cd test-project
  3. cargo add sea-orm
  4. cargo add serde -F derive
  5. cargo add serde_json
  6. 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
@anshap1719
Copy link
Sponsor Contributor

@nitn3lav Will you be creating a PR for this as well?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants