Repository: GREsau/schemars
Pull request #238 (2023-08-27 18:54:26)

add support for semver crate
Supersedes https://github.com/GREsau/schemars/pull/195 by fixing conflicts


Patch:
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()
+    }
+}


Test patch:
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::<SemverTypes>("semver")
+}