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

Schemars not understanding #[serde(serialize_with = "serialize_function")] macro #15

Closed
xylix opened this issue Feb 26, 2020 · 5 comments

Comments

@xylix
Copy link

xylix commented Feb 26, 2020

Trying to serialize a struct like this

pub enum Example {   
 #[serde(serialize_with = "serialize_function")]
    Function(String, functions::QueryFn),
}

I get

error[E0277]: the trait bound `for<'r, 's, 't0> fn(std::vec::Vec<datatype::DataType>, &'r std::collections::HashMap<&'s str, datatype::DataType>, &'t0 aw_datastore::worker::Datastore) -> std::result::Result<datatype::DataType, QueryError>: schemars::JsonSchema` is not satisfied
  --> aw-query/src/datatype.rs:18:27
   |
18 | #[derive(Clone,Serialize, JsonSchema)]
   |                           ^^^^^^^^^^ the trait `schemars::JsonSchema` is not implemented for `for<'r, 's, 't0> fn(std::vec::Vec<datatype::DataType>, &'r std::collections::HashMap<&'s str, datatype::DataType>, &'t0 aw_datastore::worker::Datastore) -> std::result::Result<datatype::DataType, QueryError>`
   |
   = note: required because of the requirements on the impl of `schemars::JsonSchema` for `(std::string::String, for<'r, 's, 't0> fn(std::vec::Vec<datatype::DataType>, &'r std::collections::HashMap<&'s str, datatype::DataType>, &'t0 aw_datastore::worker::Datastore) -> std::result::Result<datatype::DataType, QueryError>)`
   = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)

@GREsau
Copy link
Owner

GREsau commented Feb 29, 2020

I can't think of any robust way for schemars to work out the schema itself here, as it can't really "look inside" the serialize_function.

What I could certainly do though is allow you to specify another function which returns the schema you want, which would look something like:

pub enum Example {
  #[schemars(schema_with = "schema_function")]
  #[serde(serialize_with = "serialize_function")]
  Function(String, functions::QueryFn),
}

fn schema_function() -> Schema {
 // ...
}

Would that solve your problem?

@GREsau
Copy link
Owner

GREsau commented Feb 29, 2020

It should already be possible to do something similar using with, as long as you have another type that has the same schema as the desired schema for Function:

pub enum Example {
  #[schemars(with = "T")]
  #[serde(serialize_with = "serialize_function")]
  Function(String, functions::QueryFn),
}

... where T is some type that implements JsonSchema

However, when I just tried that out I realised that schemars currently doesn't respect attributes set on enum variants! I'll try to get that fixed soon

@xylix
Copy link
Author

xylix commented Mar 1, 2020

Thanks for the information. I think being able to define custom schema_function's would exactly solve the problem.

@chipsenkbeil
Copy link

@GREsau, I know there is a #[schemars(with = "T")] now, but I think having the ability to provide a custom schema function would still be very handy.

I've written custom serializers and deserializers for std::io::Error and std::io::ErrorKind such that I can ship these across the wire. I obviously cannot add JsonSchema as a derive to these types and my serialization of ErrorKind is a giant mapping of serialize_unit_variant while the io::Error just encapsulates the description, os code, and error kind fields.

If I could provide a custom schema function, I'd be able to list out the error kind variants myself.

The alternative would be to create an equivalent enum that maps to/from io::ErrorKind that derives JsonSchema and plug that enum into my other structures.

@GREsau
Copy link
Owner

GREsau commented May 15, 2020

The #[schemars(schema_with = "...")] attribute is now implemented in v0.7.3, and usable as:

pub enum Example {
  #[schemars(schema_with = "schema_function")]
  #[serde(serialize_with = "serialize_function")]
  Function(String, functions::QueryFn),
}

fn schema_function(gen: &mut SchemaGenerator) -> Schema {
 // ...
}

Could you give it a try and let me know if it works as you expect?

@GREsau GREsau closed this as completed Sep 25, 2020
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

3 participants