Skip to content

Commit

Permalink
Implement JsonSchemaAs for PickFirst (#721)
Browse files Browse the repository at this point in the history
  • Loading branch information
jonasbb authored Apr 7, 2024
2 parents 634c41f + f4145e3 commit 9e15ac3
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 0 deletions.
73 changes: 73 additions & 0 deletions serde_with/src/schemars_0_8.rs
Original file line number Diff line number Diff line change
Expand Up @@ -887,6 +887,79 @@ where
}
}

macro_rules! schema_for_pickfirst {
($( $param:ident )+) => {
impl<T, $($param,)+> JsonSchemaAs<T> for PickFirst<($( $param, )+)>
where
$( $param: JsonSchemaAs<T>, )+
{
fn schema_name() -> String {
std::format!(
concat!(
"PickFirst<(",
$( "{", stringify!($param), "}", )+
")>"
),
$( $param = <WrapSchema<T, $param>>::schema_name(), )+
)
}

fn schema_id() -> Cow<'static, str> {
std::format!(
concat!(
"serde_with::PickFirst<(",
$( "{", stringify!($param), "}", )+
")>"
),
$( $param = <WrapSchema<T, $param>>::schema_id(), )+
)
.into()
}

fn json_schema(gen: &mut SchemaGenerator) -> Schema {
let mut first = true;
let subschemas = std::vec![$(
{
let is_first = std::mem::replace(&mut first, false);
let schema = gen.subschema_for::<WrapSchema<T, $param>>();

if !is_first {
SchemaObject {
metadata: Some(Box::new(Metadata {
write_only: true,
..Default::default()
})),
subschemas: Some(Box::new(SubschemaValidation {
all_of: Some(std::vec![schema]),
..Default::default()
})),
..Default::default()
}
.into()
} else {
schema
}
}
),+];

SchemaObject {
subschemas: Some(Box::new(SubschemaValidation {
any_of: Some(subschemas),
..Default::default()
})),
..Default::default()
}
.into()
}
}
}
}

schema_for_pickfirst!(A);
schema_for_pickfirst!(A B);
schema_for_pickfirst!(A B C);
schema_for_pickfirst!(A B C D);

impl<T, TA> JsonSchemaAs<T> for SetLastValueWins<TA>
where
TA: JsonSchemaAs<T>,
Expand Down
19 changes: 19 additions & 0 deletions serde_with/tests/schemars_0_8.rs
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,14 @@ mod snapshots {
data: Vec<i32>,
}
}

pickfirst {
#[serde(transparent)]
struct Test {
#[serde_as(as = "PickFirst<(_, DisplayFromStr)>")]
value: u32
}
}
}
}

Expand Down Expand Up @@ -942,3 +950,14 @@ mod one_or_many {
check_matches_schema::<WithPreferMany>(&json!(["test", 1]));
}
}

#[test]
fn test_pickfirst() {
#[serde_as]
#[derive(JsonSchema, Serialize)]
#[serde(transparent)]
struct IntOrDisplay(#[serde_as(as = "PickFirst<(_, DisplayFromStr)>")] u32);

check_matches_schema::<IntOrDisplay>(&json!(7));
check_matches_schema::<IntOrDisplay>(&json!("17"));
}
19 changes: 19 additions & 0 deletions serde_with/tests/schemars_0_8/snapshots/pickfirst.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "PickFirst<(uint32String)>",
"anyOf": [
{
"type": "integer",
"format": "uint32",
"minimum": 0.0
},
{
"writeOnly": true,
"allOf": [
{
"type": "string"
}
]
}
]
}

0 comments on commit 9e15ac3

Please sign in to comment.