diff --git a/Cargo.lock b/Cargo.lock
index 169c4cb7..e1af5da2 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -990,6 +990,7 @@ dependencies = [
"http-body",
"http-body-util",
"indexmap",
+ "schemars",
"serde",
"serde_html_form",
"serde_json",
diff --git a/cot-core/Cargo.toml b/cot-core/Cargo.toml
index 65f66383..847f9713 100644
--- a/cot-core/Cargo.toml
+++ b/cot-core/Cargo.toml
@@ -29,7 +29,8 @@ http-body-util.workspace = true
http-body.workspace = true
http.workspace = true
indexmap.workspace = true
-serde.workspace = true
+schemars = { workspace = true, optional = true, features = ["derive"] }
+serde = { workspace = true, features = ["derive"] }
serde_html_form = { workspace = true, features = ["de", "std"] }
serde_json.workspace = true
serde_path_to_error.workspace = true
@@ -47,3 +48,4 @@ tokio.workspace = true
[features]
default = []
json = []
+schemars = ["dep:schemars"]
diff --git a/cot-core/src/html.rs b/cot-core/src/html.rs
index bdbd8ce9..10d5c2dd 100644
--- a/cot-core/src/html.rs
+++ b/cot-core/src/html.rs
@@ -54,6 +54,9 @@ use std::fmt::Write;
use askama::filters::Escaper;
use derive_more::{Deref, Display, From};
+#[cfg(feature = "schemars")]
+use schemars::JsonSchema;
+use serde::{Deserialize, Serialize};
/// A type that represents HTML content as a string.
///
@@ -65,7 +68,23 @@ use derive_more::{Deref, Display, From};
/// let html = Html::new("
Hello
");
/// assert_eq!(html.as_str(), "Hello
");
/// ```
-#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Deref, From, Display)]
+#[derive(
+ Debug,
+ Clone,
+ PartialEq,
+ Eq,
+ PartialOrd,
+ Ord,
+ Hash,
+ Default,
+ Deref,
+ From,
+ Display,
+ Serialize,
+ Deserialize,
+)]
+#[cfg_attr(feature = "schemars", derive(JsonSchema))]
+#[serde(transparent)]
pub struct Html(pub String);
impl Html {
diff --git a/cot/Cargo.toml b/cot/Cargo.toml
index f12f86d3..9e83834b 100644
--- a/cot/Cargo.toml
+++ b/cot/Cargo.toml
@@ -50,7 +50,7 @@ multer.workspace = true
password-auth = { workspace = true, features = ["std", "argon2"] }
pin-project-lite.workspace = true
redis = { workspace = true, features = ["aio", "tokio-comp"], optional = true }
-schemars = { workspace = true, optional = true }
+schemars = { workspace = true, optional = true, features = ["derive"] }
sea-query = { workspace = true, optional = true }
sea-query-binder = { workspace = true, features = ["with-chrono", "runtime-tokio"], optional = true }
serde = { workspace = true, features = ["derive"] }
@@ -113,7 +113,7 @@ postgres = ["db", "sea-query/backend-postgres", "sea-query-binder/sqlx-postgres"
mysql = ["db", "sea-query/backend-mysql", "sea-query-binder/sqlx-mysql", "sqlx/mysql"]
redis = ["cache", "dep:deadpool-redis", "dep:redis", "json"]
json = ["dep:serde_json", "cot_core/json"]
-openapi = ["json", "dep:aide", "dep:schemars"]
+openapi = ["json", "cot_core/schemars", "dep:aide", "dep:schemars"]
swagger-ui = ["openapi", "dep:swagger-ui-redist"]
live-reload = ["dep:tower-livereload"]
cache = ["json"]