-
-
Notifications
You must be signed in to change notification settings - Fork 230
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
Add serde_with #198
base: master
Are you sure you want to change the base?
Add serde_with #198
Conversation
run: cargo update -p serde --precise 1.0.142 && cargo update -p once_cell --precise 1.10.0 && cargo update -p pretty_assertions --precise 1.2.1 | ||
run: sed -i '/serde_with =/d' schemars/Cargo.toml && cargo update -p serde --precise 1.0.142 && cargo update -p once_cell --precise 1.10.0 && cargo update -p pretty_assertions --precise 1.2.1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
while this makes ci green, it's not really feasible on release.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AFAICT with serde_with even as an optional dependency we bump MSRV to 1.60
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The latest version supported below is 1.14
One thing worth considering is adding SerdeWith adapters with a PhantomType to make it easy to define schemas: pub struct Same<T>(PhantomData<T>);
impl<'de, _T, T: Deserialize<'de>> DeserializeAs<'de, T> for Same<_T> {
fn deserialize_as<D: Deserializer<'de>>(deserializer: D) -> Result<T, D::Error> {
T::deserialize(deserializer)
}
}
impl<'de, _T, T: Serialize> SerializeAs<T> for Same<_T> {
fn serialize_as<S: Serializer>(it: &T, serializer: S) -> Result<S::Ok, S::Error> {
it.serialize(serializer)
}
}
impl<T: JsonSchema> JsonSchema for Same<T> {
fn schema_name() -> String {
T::schema_name()
}
fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
T::json_schema(gen)
}
fn is_referenceable() -> bool {
T::is_referenceable()
}
fn _schemars_private_non_optional_json_schema(
gen: &mut schemars::gen::SchemaGenerator,
) -> schemars::schema::Schema {
T::_schemars_private_non_optional_json_schema(gen)
}
fn _schemars_private_is_option() -> bool {
T::_schemars_private_is_option()
}
} |
Hi, interesting PR. From the last comment, it seems there are some issues due to type inference. I'm not familiar with schemars, so maybe my conclusion is nonsense. serde_with quite heavily relies on inference for the whole Without that option in schemars, you can fake the type inference, with another type. This seems to work. The schema looks ok to me. pub struct Schema<T: ?Sized, TAs>(PhantomData<T>, PhantomData<TAs>);
impl<T> schemars::JsonSchema for Schema<T, Same>
where
T: schemars::JsonSchema,
{
fn schema_name() -> alloc::string::String {
T::schema_name()
}
fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
T::json_schema(gen)
}
}
impl<T> schemars::JsonSchema for Schema<T, DisplayFromStr> {
fn schema_name() -> alloc::string::String {
alloc::string::String::schema_name()
}
fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
alloc::string::String::json_schema(gen)
}
}
impl<T> schemars::JsonSchema for Schema<Option<T>, NoneAsEmptyString> {
fn schema_name() -> alloc::string::String {
<Option<alloc::string::String>>::schema_name()
}
fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
<Option<alloc::string::String>>::json_schema(gen)
}
}
impl<T, TAs> schemars::JsonSchema for Schema<alloc::boxed::Box<T>, alloc::boxed::Box<TAs>>
where
Schema<T, TAs>: schemars::JsonSchema,
{
fn schema_name() -> alloc::string::String {
<alloc::boxed::Box<Schema<T, TAs>>>::schema_name()
}
fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
<alloc::boxed::Box<Schema<T, TAs>>>::json_schema(gen)
}
}
impl<T, TAs> schemars::JsonSchema for Schema<alloc::vec::Vec<T>, alloc::vec::Vec<TAs>>
where
Schema<T, TAs>: schemars::JsonSchema,
{
fn schema_name() -> alloc::string::String {
<alloc::vec::Vec<Schema<T, TAs>>>::schema_name()
}
fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
<alloc::vec::Vec<Schema<T, TAs>>>::json_schema(gen)
}
}
#[test]
fn schemas() {
use alloc::{borrow::ToOwned, boxed::Box, string::String, vec::Vec};
#[derive(schemars::JsonSchema)]
struct A {
a: u32,
#[schemars(with = "Schema::<u32, DisplayFromStr>")]
b: u32,
#[schemars(with = "Schema::<Box<u32>, Box<DisplayFromStr>>")]
c: Box<u32>,
#[schemars(with = "Schema::<Box<u32>, Box<Same>>")]
d: Box<u32>,
#[schemars(with = "Schema::<Vec<u32>, Vec<DisplayFromStr>>")]
e: Vec<u32>,
#[schemars(with = "Schema::<Option<String>, NoneAsEmptyString>")]
f: Option<String>,
}
let schema = schemars::schema_for!(A);
expect_test::expect![[r##"
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "A",
"type": "object",
"required": [
"a",
"b",
"c",
"d",
"e",
"f"
],
"properties": {
"a": {
"type": "integer",
"format": "uint32",
"minimum": 0.0
},
"b": {
"$ref": "#/definitions/String"
},
"c": {
"$ref": "#/definitions/String"
},
"d": {
"$ref": "#/definitions/uint32"
},
"e": {
"$ref": "#/definitions/Array_of_String"
},
"f": {
"$ref": "#/definitions/Nullable_String"
}
},
"definitions": {
"Array_of_String": {
"type": "array",
"items": {
"$ref": "#/definitions/String"
}
},
"Nullable_String": {
"type": [
"string",
"null"
]
},
"String": {
"type": "string"
},
"uint32": {
"type": "integer",
"format": "uint32",
"minimum": 0.0
}
}
}"##]]
.assert_eq(&serde_json::to_string_pretty(&schema).unwrap());
} If you want to go that way the question is how to generate the #[serde_with::serde_as(schema = true)]
#[derive(serde::Serialize, schemars::JsonSchema)]
struct Foo {...} Some implementations in this PR seem slightly wrong. Somebody with better schema knowledge might want to double check them. For example, |
sound reasonable, if this pr is considered, I'll update these and have a look at the rest. |
Any updates on this PR, I'm currently blocked on it |
@Kixiron This PR has some issues with type inference (relatively important for |
If I get a ok by @GREsau that this would be considered I'd try incorporating the feedback above. But feel free to ask on Maybe at some point forking could also make sense. |
Since there appears to be some interest in better integrating schemars and serde_with, I threw together this PoC jonasbb/serde_with#623 based on my previous comment. I am happy to review contributions for that, but cannot build it myself as I lack the knowledge about JSON schemas and this crate. I think the PR is enough of a foundation that extending it is possible without much serde_with knowledge. |
I've been working on getting this integrated over on the For those interested in following along some basic support got added in jonasbb/serde_with#666 and more is currently being added in jonasbb/serde_with#676. |
No description provided.