Add transform = ... attribute (#312)

This allows running arbitrary transforms on generated schemas when deriving `JsonSchema`
This commit is contained in:
Graham Esau 2024-08-10 09:56:52 +01:00 committed by GitHub
parent 29067a0331
commit 14b06e71ba
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 173 additions and 10 deletions

View file

@ -0,0 +1,25 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "External",
"oneOf": [
{
"type": "string",
"const": "Unit",
"propertyCount": 0,
"upperType": "STRING"
},
{
"type": "object",
"properties": {
"NewType": true
},
"required": [
"NewType"
],
"additionalProperties": false,
"propertyCount": 1,
"upperType": "OBJECT"
}
],
"propertyCount": 0
}

View file

@ -0,0 +1,20 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "Struct",
"type": "object",
"properties": {
"value": true,
"int": {
"type": "integer",
"format": "int32",
"propertyCount": 0,
"upperType": "INTEGER"
}
},
"required": [
"value",
"int"
],
"upperType": "OBJECT",
"propertyCount": 2
}

View file

@ -17,7 +17,7 @@ struct Struct {
}
#[test]
fn doc_comments_struct() -> TestResult {
fn extend_struct() -> TestResult {
test_default_generated_schema::<Struct>("extend_struct")
}
@ -36,7 +36,7 @@ enum External {
}
#[test]
fn doc_comments_enum_external() -> TestResult {
fn extend_enum_external() -> TestResult {
test_default_generated_schema::<External>("extend_enum_external")
}
@ -53,7 +53,7 @@ enum Internal {
}
#[test]
fn doc_comments_enum_internal() -> TestResult {
fn extend_enum_internal() -> TestResult {
test_default_generated_schema::<Internal>("extend_enum_internal")
}
@ -72,7 +72,7 @@ enum Untagged {
}
#[test]
fn doc_comments_enum_untagged() -> TestResult {
fn extend_enum_untagged() -> TestResult {
test_default_generated_schema::<Untagged>("extend_enum_untagged")
}
@ -91,6 +91,6 @@ enum Adjacent {
}
#[test]
fn doc_comments_enum_adjacent() -> TestResult {
fn extend_enum_adjacent() -> TestResult {
test_default_generated_schema::<Adjacent>("extend_enum_adjacent")
}

View file

@ -0,0 +1,51 @@
mod util;
use schemars::{transform::RecursiveTransform, JsonSchema, Schema};
use serde_json::Value;
use util::*;
fn capitalize_type(schema: &mut Schema) {
if let Some(obj) = schema.as_object_mut() {
if let Some(Value::String(ty)) = obj.get("type") {
obj.insert("upperType".to_owned(), ty.to_uppercase().into());
}
}
}
fn insert_property_count(schema: &mut Schema) {
if let Some(obj) = schema.as_object_mut() {
let count = obj
.get("properties")
.and_then(|p| p.as_object())
.map_or(0, |p| p.len());
obj.insert("propertyCount".to_owned(), count.into());
}
}
#[allow(dead_code)]
#[derive(JsonSchema)]
#[schemars(transform = RecursiveTransform(capitalize_type), transform = insert_property_count)]
struct Struct {
value: Value,
#[schemars(transform = insert_property_count)]
int: i32,
}
#[test]
fn transform_struct() -> TestResult {
test_default_generated_schema::<Struct>("transform_struct")
}
#[allow(dead_code)]
#[derive(JsonSchema)]
#[schemars(transform = RecursiveTransform(capitalize_type), transform = insert_property_count)]
enum External {
#[schemars(transform = insert_property_count)]
Unit,
#[schemars(transform = insert_property_count)]
NewType(Value),
}
#[test]
fn transform_enum_external() -> TestResult {
test_default_generated_schema::<External>("transform_enum_external")
}

View file

@ -0,0 +1,7 @@
use schemars::JsonSchema;
#[derive(JsonSchema)]
#[schemars(transform = "x")]
pub struct Struct;
fn main() {}

View file

@ -0,0 +1,6 @@
error: Expected a `fn(&mut Schema)` or other value implementing `schemars::transform::Transform`, found `&str`.
Did you mean `[schemars(transform = x)]`?
--> tests/ui/transform_str.rs:4:24
|
4 | #[schemars(transform = "x")]
| ^^^