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

Unable to (de)serialize nested JSON Blobs using serde Traits #676

Closed
mara-schulke opened this issue Apr 19, 2022 · 7 comments · Fixed by #794
Closed

Unable to (de)serialize nested JSON Blobs using serde Traits #676

mara-schulke opened this issue Apr 19, 2022 · 7 comments · Fixed by #794
Assignees
Milestone

Comments

@mara-schulke
Copy link

Description

We have a database schema where we save (from the db pov) untyped json blobs into the database + some metadata columns. We have a serde compatible struct for describing the blobs on the rust side and expected to be able to use the #[sea_orm(db_type = "Json")] as annotation to be able to deserialize the JSON col into the rust struct on select.

Steps to Reproduce

Rust

use some_external_crate::priding::our::type::SomeStruct;
use sea_orm::entity::prelude::*;
use serde::{Deserialize, Serialize};

#[derive(Clone, Debug, Deserialize, Serialize, Eq, PartialEq, DeriveEntityModel)]
#[sea_orm(table_name = "table_name")]
pub struct Model {
    #[sea_orm(primary_key)]
    pub id: String,
    #[sea_orm(db_type = "Json")]
    pub details: SomeStruct,
    pub refreshed_at: DateTime,
}

#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}

...

SQL

CREATE TABLE table_name (
    id varchar(64) PRIMARY KEY,
    refreshed_at   timestamptz NOT NULL,
    details        jsonb NOT NULL
);

Expected Behavior

The details field of the Model should be deserialized from json / jsonb columns into the SomeStruct type in rust.

Actual Behavior

"the trait bound `sea_orm::Value: From<SomeStruct>` is not satisfied"

Reproduces How Often

Every time.

Versions

0.7.1

Additional Information

None

@billy1624
Copy link
Member

Hey @schulke-214, please refer to https://github.com/SeaQL/sea-orm/blob/master/issues/400/src/model.rs on how to implement necessary traits for custom model fields

@mara-schulke
Copy link
Author

mara-schulke commented Apr 20, 2022

It comes from an external crate. We are unable to implement your traits for external types. Also i would expect sea-orm to be compliant with standard rust ecosystem traits such as Serialize and Deserialize instead of building your own type infrastructure around it. Most crates wont be compatible with sea orm this way.

@billy1624
Copy link
Member

This isn't ideal but you can do it with newtype pattern.

pub struct MySomeStruct(SomeStruct);

impl SomeTrait for MySomeStruct {
    ...
}

@mara-schulke
Copy link
Author

If that is the only reaction to this issue we are not going to be able to use sea orm sadly. I think a lot of things are done excellent about it, but this is just some missing trait implementations on your side:

https://github.com/SeaQL/sea-query/blob/master/src/value.rs#L304-L308

mod with_json {
    ...
 
    impl<T> From<T> for sea_orm::Value
    where
        T: Serialize,
        for<'de> T: Deserialize<'de>
    {
        fn from(json: T) -> Self {
            if let Some(value) = serde_json::to_value(&json) {
                return Self::Value::Json(Some(Box::new(value))
            }

            None
        }
    }


    impl<T> Nullable for T
    where
        T: Serialize,
        for<'de> T: Deserialize<'de>
    {
        fn null() -> Value {
            Value::Json(None)
        }
    }

    impl<T> ValueType for T
    where
        T: Serialize,
        for<'de> T: Deserialize<'de>
    {
        fn try_from(v: Value) -> Result<Self, ValueTypeErr> {
            match v {
                Value::Json(Some(x)) => serde_json::from_value(x.as_ref()),
                _ => Err(ValueTypeErr),
            }
        }

        fn type_name() -> String {
            "Json".to_owned()
        }

        fn column_type() -> ColumnType {
           // take smh from the annotation #[sea_orm(db_type="X")
        }
    }
} 

@tyt2y3
Copy link
Member

tyt2y3 commented Apr 24, 2022

@schulke-214 I think you raised an interesting use case
Can you open a PR on that code snippet you gave?
It'd also be great if we can add some test cases to tests/serde_json.rs so that it won't be broken in the future.

@billy1624 billy1624 self-assigned this May 4, 2022
@billy1624
Copy link
Member

Hey @schulke-214, feel free to review #696

@tyt2y3
Copy link
Member

tyt2y3 commented Jun 14, 2022

#696 (comment)

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

Successfully merging a pull request may close this issue.

3 participants