Skip to content

Commit 88e9879

Browse files
authored
Merge pull request #682 from swlynch99/schemars-custom-with
2 parents 6ecde3c + 1c9131f commit 88e9879

File tree

10 files changed

+196
-62
lines changed

10 files changed

+196
-62
lines changed

Cargo.lock

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ license = "MIT OR Apache-2.0"
1212
readme = "README.md"
1313
repository = "https://github.com/jonasbb/serde_with/"
1414
rust-version = "1.64"
15-
version = "3.5.0"
15+
version = "3.5.1"
1616

1717
[workspace.metadata.release]
1818
consolidate-commits = true

README.md

+7-7
Original file line numberDiff line numberDiff line change
@@ -183,14 +183,14 @@ Foo::Bytes {
183183
}
184184
```
185185

186-
[`DisplayFromStr`]: https://docs.rs/serde_with/3.5.0/serde_with/struct.DisplayFromStr.html
187-
[`with_prefix!`]: https://docs.rs/serde_with/3.5.0/serde_with/macro.with_prefix.html
188-
[feature flags]: https://docs.rs/serde_with/3.5.0/serde_with/guide/feature_flags/index.html
189-
[skip_serializing_none]: https://docs.rs/serde_with/3.5.0/serde_with/attr.skip_serializing_none.html
190-
[StringWithSeparator]: https://docs.rs/serde_with/3.5.0/serde_with/struct.StringWithSeparator.html
191-
[user guide]: https://docs.rs/serde_with/3.5.0/serde_with/guide/index.html
186+
[`DisplayFromStr`]: https://docs.rs/serde_with/3.5.1/serde_with/struct.DisplayFromStr.html
187+
[`with_prefix!`]: https://docs.rs/serde_with/3.5.1/serde_with/macro.with_prefix.html
188+
[feature flags]: https://docs.rs/serde_with/3.5.1/serde_with/guide/feature_flags/index.html
189+
[skip_serializing_none]: https://docs.rs/serde_with/3.5.1/serde_with/attr.skip_serializing_none.html
190+
[StringWithSeparator]: https://docs.rs/serde_with/3.5.1/serde_with/struct.StringWithSeparator.html
191+
[user guide]: https://docs.rs/serde_with/3.5.1/serde_with/guide/index.html
192192
[with-annotation]: https://serde.rs/field-attrs.html#with
193-
[as-annotation]: https://docs.rs/serde_with/3.5.0/serde_with/guide/serde_as/index.html
193+
[as-annotation]: https://docs.rs/serde_with/3.5.1/serde_with/guide/serde_as/index.html
194194

195195
## License
196196

serde_with/CHANGELOG.md

+7
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
77

88
## [Unreleased]
99

10+
## [3.5.1] - 2024-01-23
11+
12+
### Fixed
13+
14+
* The `serde_as` macro now better detects existing `schemars` attributes on fields and incorporates them (#682)
15+
This avoids errors on existing `#[schemars(with = ...)]` annotations.
16+
1017
## [3.5.0] - 2024-01-20
1118

1219
### Added

serde_with/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ schemars_0_8 = {package = "schemars", version = "0.8.16", optional = true, defau
134134
# https://github.com/jonasbb/serde_with/blob/eb1965a74a3be073ecd13ec05f02a01bc1c44309/serde_with/src/flatten_maybe.rs#L67
135135
serde = {version = "1.0.152", default-features = false, features = ["derive"] }
136136
serde_json = {version = "1.0.45", optional = true, default-features = false}
137-
serde_with_macros = {path = "../serde_with_macros", version = "=3.5.0", optional = true}
137+
serde_with_macros = {path = "../serde_with_macros", version = "=3.5.1", optional = true}
138138
time_0_3 = {package = "time", version = "~0.3.11", optional = true, default-features = false}
139139

140140
[dev-dependencies]

serde_with/src/lib.rs

+13-13
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
#![doc(test(attr(warn(rust_2018_idioms))))]
2727
// Not needed for 2018 edition and conflicts with `rust_2018_idioms`
2828
#![doc(test(no_crate_inject))]
29-
#![doc(html_root_url = "https://docs.rs/serde_with/3.5.0/")]
29+
#![doc(html_root_url = "https://docs.rs/serde_with/3.5.1/")]
3030
#![cfg_attr(docsrs, feature(doc_cfg))]
3131
#![allow(
3232
// clippy is broken and shows wrong warnings
@@ -281,14 +281,14 @@
281281
//! # }
282282
//! ```
283283
//!
284-
//! [`DisplayFromStr`]: https://docs.rs/serde_with/3.5.0/serde_with/struct.DisplayFromStr.html
285-
//! [`with_prefix!`]: https://docs.rs/serde_with/3.5.0/serde_with/macro.with_prefix.html
286-
//! [feature flags]: https://docs.rs/serde_with/3.5.0/serde_with/guide/feature_flags/index.html
287-
//! [skip_serializing_none]: https://docs.rs/serde_with/3.5.0/serde_with/attr.skip_serializing_none.html
288-
//! [StringWithSeparator]: https://docs.rs/serde_with/3.5.0/serde_with/struct.StringWithSeparator.html
289-
//! [user guide]: https://docs.rs/serde_with/3.5.0/serde_with/guide/index.html
284+
//! [`DisplayFromStr`]: https://docs.rs/serde_with/3.5.1/serde_with/struct.DisplayFromStr.html
285+
//! [`with_prefix!`]: https://docs.rs/serde_with/3.5.1/serde_with/macro.with_prefix.html
286+
//! [feature flags]: https://docs.rs/serde_with/3.5.1/serde_with/guide/feature_flags/index.html
287+
//! [skip_serializing_none]: https://docs.rs/serde_with/3.5.1/serde_with/attr.skip_serializing_none.html
288+
//! [StringWithSeparator]: https://docs.rs/serde_with/3.5.1/serde_with/struct.StringWithSeparator.html
289+
//! [user guide]: https://docs.rs/serde_with/3.5.1/serde_with/guide/index.html
290290
//! [with-annotation]: https://serde.rs/field-attrs.html#with
291-
//! [as-annotation]: https://docs.rs/serde_with/3.5.0/serde_with/guide/serde_as/index.html
291+
//! [as-annotation]: https://docs.rs/serde_with/3.5.1/serde_with/guide/serde_as/index.html
292292
293293
#[cfg(feature = "alloc")]
294294
extern crate alloc;
@@ -498,7 +498,7 @@ pub use serde_with_macros::*;
498498
/// # }
499499
/// ```
500500
///
501-
/// [serde_as]: https://docs.rs/serde_with/3.5.0/serde_with/attr.serde_as.html
501+
/// [serde_as]: https://docs.rs/serde_with/3.5.1/serde_with/attr.serde_as.html
502502
pub struct As<T: ?Sized>(PhantomData<T>);
503503

504504
/// Adapter to convert from `serde_as` to the serde traits.
@@ -930,7 +930,7 @@ pub struct BytesOrString;
930930
/// ```
931931
///
932932
/// [`chrono::Duration`]: ::chrono_0_4::Duration
933-
/// [feature flag]: https://docs.rs/serde_with/3.5.0/serde_with/guide/feature_flags/index.html
933+
/// [feature flag]: https://docs.rs/serde_with/3.5.1/serde_with/guide/feature_flags/index.html
934934
pub struct DurationSeconds<
935935
FORMAT: formats::Format = u64,
936936
STRICTNESS: formats::Strictness = formats::Strict,
@@ -1062,7 +1062,7 @@ pub struct DurationSeconds<
10621062
/// ```
10631063
///
10641064
/// [`chrono::Duration`]: ::chrono_0_4::Duration
1065-
/// [feature flag]: https://docs.rs/serde_with/3.5.0/serde_with/guide/feature_flags/index.html
1065+
/// [feature flag]: https://docs.rs/serde_with/3.5.1/serde_with/guide/feature_flags/index.html
10661066
pub struct DurationSecondsWithFrac<
10671067
FORMAT: formats::Format = f64,
10681068
STRICTNESS: formats::Strictness = formats::Strict,
@@ -1264,7 +1264,7 @@ pub struct DurationNanoSecondsWithFrac<
12641264
/// [`SystemTime`]: std::time::SystemTime
12651265
/// [`chrono::DateTime<Local>`]: ::chrono_0_4::DateTime
12661266
/// [`chrono::DateTime<Utc>`]: ::chrono_0_4::DateTime
1267-
/// [feature flag]: https://docs.rs/serde_with/3.5.0/serde_with/guide/feature_flags/index.html
1267+
/// [feature flag]: https://docs.rs/serde_with/3.5.1/serde_with/guide/feature_flags/index.html
12681268
pub struct TimestampSeconds<
12691269
FORMAT: formats::Format = i64,
12701270
STRICTNESS: formats::Strictness = formats::Strict,
@@ -1406,7 +1406,7 @@ pub struct TimestampSeconds<
14061406
/// [`chrono::DateTime<Local>`]: ::chrono_0_4::DateTime
14071407
/// [`chrono::DateTime<Utc>`]: ::chrono_0_4::DateTime
14081408
/// [NaiveDateTime]: ::chrono_0_4::NaiveDateTime
1409-
/// [feature flag]: https://docs.rs/serde_with/3.5.0/serde_with/guide/feature_flags/index.html
1409+
/// [feature flag]: https://docs.rs/serde_with/3.5.1/serde_with/guide/feature_flags/index.html
14101410
pub struct TimestampSecondsWithFrac<
14111411
FORMAT: formats::Format = f64,
14121412
STRICTNESS: formats::Strictness = formats::Strict,

serde_with/tests/schemars_0_8.rs

+30-5
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ macro_rules! declare_snapshot_test {
3333
#[test]
3434
$(#[$tattr])*
3535
fn $test() {
36-
#[serde_with::serde_as]
36+
#[serde_as]
3737
#[derive(JsonSchema, Serialize)]
3838
$( #[$stattr] )*
3939
struct $name {
@@ -62,7 +62,7 @@ fn schemars_basic() {
6262
use ::schemars_0_8::JsonSchema;
6363
use serde::Serialize;
6464

65-
#[serde_with::serde_as]
65+
#[serde_as]
6666
#[derive(JsonSchema, Serialize)]
6767
#[schemars(crate = "::schemars_0_8")]
6868
struct Basic {
@@ -95,6 +95,31 @@ fn schemars_basic() {
9595
expected.assert_eq(&schema);
9696
}
9797

98+
#[test]
99+
fn schemars_custom_with() {
100+
#[serde_as]
101+
#[derive(JsonSchema, Serialize)]
102+
struct Test {
103+
#[serde_as(as = "DisplayFromStr")]
104+
#[schemars(with = "i32")]
105+
custom: i32,
106+
107+
#[serde_as(as = "DisplayFromStr")]
108+
#[cfg_attr(any(), schemars(with = "i32"))]
109+
with_disabled: i32,
110+
111+
#[serde_as(as = "DisplayFromStr")]
112+
#[cfg_attr(all(), schemars(with = "i32"))]
113+
always_enabled: i32,
114+
}
115+
116+
check_matches_schema::<Test>(&json!({
117+
"custom": 3,
118+
"with_disabled": "5",
119+
"always_enabled": 7,
120+
}));
121+
}
122+
98123
mod test_std {
99124
use super::*;
100125
use std::collections::{BTreeMap, BTreeSet, VecDeque};
@@ -220,15 +245,15 @@ mod snapshots {
220245
mod derive {
221246
use super::*;
222247

223-
#[serde_with::serde_as]
248+
#[serde_as]
224249
#[derive(Serialize)]
225250
#[cfg_attr(all(), derive(JsonSchema))]
226251
struct Enabled {
227252
#[serde_as(as = "DisplayFromStr")]
228253
field: u32,
229254
}
230255

231-
#[serde_with::serde_as]
256+
#[serde_as]
232257
#[derive(Serialize)]
233258
#[cfg_attr(any(), derive(JsonSchema))]
234259
struct Disabled {
@@ -247,7 +272,7 @@ mod derive {
247272
mod array {
248273
use super::*;
249274

250-
#[serde_with::serde_as]
275+
#[serde_as]
251276
#[derive(JsonSchema, Serialize)]
252277
struct FixedArray {
253278
#[serde_as(as = "[_; 3]")]

serde_with_macros/CHANGELOG.md

+7
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
77

88
## [Unreleased]
99

10+
## [3.5.1] - 2024-01-23
11+
12+
### Fixed
13+
14+
* The `serde_as` macro now better detects existing `schemars` attributes on fields and incorporates them (#682)
15+
This avoids errors on existing `#[schemars(with = ...)]` annotations.
16+
1017
## [3.5.0] - 2024-01-20
1118

1219
### Added

serde_with_macros/src/lib.rs

+31-10
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
#![doc(test(attr(warn(rust_2018_idioms))))]
2727
// Not needed for 2018 edition and conflicts with `rust_2018_idioms`
2828
#![doc(test(no_crate_inject))]
29-
#![doc(html_root_url = "https://docs.rs/serde_with_macros/3.5.0/")]
29+
#![doc(html_root_url = "https://docs.rs/serde_with_macros/3.5.1/")]
3030
// Necessary to silence the warning about clippy::unknown_clippy_lints on nightly
3131
#![allow(renamed_and_removed_lints)]
3232
// Necessary for nightly clippy lints
@@ -602,8 +602,8 @@ fn field_has_attribute(field: &Field, namespace: &str, name: &str) -> bool {
602602
/// It will also work if the relevant derive is behind a `#[cfg_attr]` attribute
603603
/// and propagate the `#[cfg_attr]` to the various `#[schemars]` field attributes.
604604
///
605-
/// [`serde_as`]: https://docs.rs/serde_with/3.5.0/serde_with/guide/index.html
606-
/// [re-exporting `serde_as`]: https://docs.rs/serde_with/3.5.0/serde_with/guide/serde_as/index.html#re-exporting-serde_as
605+
/// [`serde_as`]: https://docs.rs/serde_with/3.5.1/serde_with/guide/index.html
606+
/// [re-exporting `serde_as`]: https://docs.rs/serde_with/3.5.1/serde_with/guide/serde_as/index.html#re-exporting-serde_as
607607
#[proc_macro_attribute]
608608
pub fn serde_as(args: TokenStream, input: TokenStream) -> TokenStream {
609609
#[derive(FromMeta)]
@@ -782,10 +782,19 @@ fn serde_as_add_attr_to_field(
782782
field.attrs.push(attr);
783783

784784
if let Some(cfg) = schemars_config.cfg_expr() {
785+
let with_cfg = crate::utils::schemars_with_attr_if(
786+
&field.attrs,
787+
&["with", "serialize_with", "deserialize_with"],
788+
)?;
785789
let attr_inner_tokens =
786790
quote!(#serde_with_crate_path::Schema::<#type_original, #replacement_type>)
787791
.to_string();
788-
let attr = parse_quote!(#[cfg_attr(#cfg, schemars(with = #attr_inner_tokens))]);
792+
let attr = parse_quote! {
793+
#[cfg_attr(
794+
all(#cfg, not(#with_cfg)),
795+
schemars(with = #attr_inner_tokens))
796+
]
797+
};
789798
field.attrs.push(attr);
790799
}
791800
}
@@ -800,11 +809,17 @@ fn serde_as_add_attr_to_field(
800809
field.attrs.push(attr);
801810

802811
if let Some(cfg) = schemars_config.cfg_expr() {
812+
let with_cfg =
813+
crate::utils::schemars_with_attr_if(&field.attrs, &["with", "deserialize_with"])?;
803814
let attr_inner_tokens =
804815
quote!(#serde_with_crate_path::Schema::<#type_original, #replacement_type>::deserialize)
805816
.to_string();
806-
let attr =
807-
parse_quote!(#[cfg_attr(#cfg, schemars(deserialize_with = #attr_inner_tokens))]);
817+
let attr = parse_quote! {
818+
#[cfg_attr(
819+
all(#cfg, not(#with_cfg)),
820+
schemars(deserialize_with = #attr_inner_tokens))
821+
]
822+
};
808823
field.attrs.push(attr);
809824
}
810825
}
@@ -816,11 +831,17 @@ fn serde_as_add_attr_to_field(
816831
field.attrs.push(attr);
817832

818833
if let Some(cfg) = schemars_config.cfg_expr() {
834+
let with_cfg =
835+
crate::utils::schemars_with_attr_if(&field.attrs, &["with", "serialize_with"])?;
819836
let attr_inner_tokens =
820837
quote!(#serde_with_crate_path::Schema::<#type_original, #replacement_type>::serialize)
821838
.to_string();
822-
let attr =
823-
parse_quote!(#[cfg_attr(#cfg, schemars(serialize_with = #attr_inner_tokens))]);
839+
let attr = parse_quote! {
840+
#[cfg_attr(
841+
all(#cfg, not(#with_cfg)),
842+
schemars(serialize_with = #attr_inner_tokens))
843+
]
844+
};
824845
field.attrs.push(attr);
825846
}
826847
}
@@ -1057,7 +1078,7 @@ fn has_type_embedded(type_: &Type, embedded_type: &syn::Ident) -> bool {
10571078
/// [`Display`]: std::fmt::Display
10581079
/// [`FromStr`]: std::str::FromStr
10591080
/// [cargo-toml-rename]: https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#renaming-dependencies-in-cargotoml
1060-
/// [serde-as-crate]: https://docs.rs/serde_with/3.5.0/serde_with/guide/serde_as/index.html#re-exporting-serde_as
1081+
/// [serde-as-crate]: https://docs.rs/serde_with/3.5.1/serde_with/guide/serde_as/index.html#re-exporting-serde_as
10611082
/// [serde-crate]: https://serde.rs/container-attrs.html#crate
10621083
#[proc_macro_derive(DeserializeFromStr, attributes(serde_with))]
10631084
pub fn derive_deserialize_fromstr(item: TokenStream) -> TokenStream {
@@ -1177,7 +1198,7 @@ fn deserialize_fromstr(mut input: DeriveInput, serde_with_crate_path: Path) -> T
11771198
/// [`Display`]: std::fmt::Display
11781199
/// [`FromStr`]: std::str::FromStr
11791200
/// [cargo-toml-rename]: https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#renaming-dependencies-in-cargotoml
1180-
/// [serde-as-crate]: https://docs.rs/serde_with/3.5.0/serde_with/guide/serde_as/index.html#re-exporting-serde_as
1201+
/// [serde-as-crate]: https://docs.rs/serde_with/3.5.1/serde_with/guide/serde_as/index.html#re-exporting-serde_as
11811202
/// [serde-crate]: https://serde.rs/container-attrs.html#crate
11821203
#[proc_macro_derive(SerializeDisplay, attributes(serde_with))]
11831204
pub fn derive_serialize_display(item: TokenStream) -> TokenStream {

0 commit comments

Comments
 (0)