diff --git a/CHANGELOG.md b/CHANGELOG.md index 9025e4e..63cd2f2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## [0.8.13] - _in-dev_ +### Added: + +- Implement `JsonSchema` for `semver::Version` (https://github.com/GREsau/schemars/pull/195 / https://github.com/GREsau/schemars/pull/238) + ### Changed: - Minimum supported rust version is now 1.56.0 diff --git a/README.md b/README.md index ddffb42..8e5a39c 100644 --- a/README.md +++ b/README.md @@ -270,6 +270,7 @@ Schemars can implement `JsonSchema` on types from several popular crates, enable - `rust_decimal` - [rust_decimal](https://crates.io/crates/rust_decimal) (^1.0) - `bigdecimal` - [bigdecimal](https://crates.io/crates/bigdecimal) (^0.3) - `smol_str` - [smol_str](https://crates.io/crates/smol_str) (^0.1.17) +- `semver` - [semver](https://crates.io/crates/semver) (^1.0.9) For example, to implement `JsonSchema` on types from `chrono`, enable it as a feature in the `schemars` dependency in your `Cargo.toml` like so: diff --git a/docs/4-features.md b/docs/4-features.md index dc3cc85..5112773 100644 --- a/docs/4-features.md +++ b/docs/4-features.md @@ -25,6 +25,7 @@ Schemars can implement `JsonSchema` on types from several popular crates, enable - `rust_decimal` - [rust_decimal](https://crates.io/crates/rust_decimal) (^1.0) - `bigdecimal` - [bigdecimal](https://crates.io/crates/bigdecimal) (^0.3) - `smol_str` - [smol_str](https://crates.io/crates/smol_str) (^0.1.17) +- `semver` - [semver](https://crates.io/crates/semver) (^1.0.9) For example, to implement `JsonSchema` on types from `chrono`, enable it as a feature in the `schemars` dependency in your `Cargo.toml` like so: diff --git a/schemars/Cargo.toml b/schemars/Cargo.toml index e02f0e0..aaf7b3d 100644 --- a/schemars/Cargo.toml +++ b/schemars/Cargo.toml @@ -33,6 +33,7 @@ rust_decimal = { version = "1", default-features = false, optional = true } bigdecimal = { version = "0.3", default-features = false, optional = true } enumset = { version = "1.0", optional = true } smol_str = { version = "0.1.17", optional = true } +semver = { version = "1.0.9", features = ["serde"], optional = true } [dev-dependencies] pretty_assertions = "1.2.1" @@ -108,5 +109,9 @@ required-features = ["enumset"] name = "smol_str" required-features = ["smol_str"] +[[test]] +name = "semver" +required-features = ["semver"] + [package.metadata.docs.rs] all-features = true diff --git a/schemars/src/json_schema_impls/mod.rs b/schemars/src/json_schema_impls/mod.rs index 490a544..d96bf38 100644 --- a/schemars/src/json_schema_impls/mod.rs +++ b/schemars/src/json_schema_impls/mod.rs @@ -60,6 +60,8 @@ mod maps; mod nonzero_signed; mod nonzero_unsigned; mod primitives; +#[cfg(feature = "semver")] +mod semver; mod sequences; mod serdejson; #[cfg(feature = "smallvec")] diff --git a/schemars/src/json_schema_impls/semver.rs b/schemars/src/json_schema_impls/semver.rs new file mode 100644 index 0000000..37c1d24 --- /dev/null +++ b/schemars/src/json_schema_impls/semver.rs @@ -0,0 +1,25 @@ +use crate::gen::SchemaGenerator; +use crate::schema::*; +use crate::JsonSchema; +use semver::Version; + +impl JsonSchema for Version { + no_ref_schema!(); + + fn schema_name() -> String { + "Version".to_owned() + } + + fn json_schema(_: &mut SchemaGenerator) -> Schema { + SchemaObject { + instance_type: Some(InstanceType::String.into()), + string: Some(Box::new(StringValidation { + // https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string + pattern: Some(r"^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$".to_owned()), + ..Default::default() + })), + ..Default::default() + } + .into() + } +} diff --git a/schemars/tests/expected/semver.json b/schemars/tests/expected/semver.json new file mode 100644 index 0000000..d87ad04 --- /dev/null +++ b/schemars/tests/expected/semver.json @@ -0,0 +1,12 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "SemverTypes", + "type": "object", + "required": ["version"], + "properties": { + "version": { + "type": "string", + "pattern": "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$" + } + } +} diff --git a/schemars/tests/semver.rs b/schemars/tests/semver.rs new file mode 100644 index 0000000..617e508 --- /dev/null +++ b/schemars/tests/semver.rs @@ -0,0 +1,15 @@ +mod util; +use schemars::JsonSchema; +use semver::Version; +use util::*; + +#[allow(dead_code)] +#[derive(JsonSchema)] +struct SemverTypes { + version: Version, +} + +#[test] +fn semver_types() -> TestResult { + test_default_generated_schema::("semver") +}