pub struct CanonicalSchema {
pub name: Option<String>,
pub schema: Value,
}Expand description
A JSON Schema with, when the type has one, a stable component name (the type’s title).
Fields§
§name: Option<String>The component name projections use (RepositoryInfo); None for an anonymous
schema such as the empty input.
schema: ValueThe schema itself, without $schema; nested types live under $defs.
Implementations§
Source§impl CanonicalSchema
impl CanonicalSchema
Sourcepub fn of<T: JsonSchema>() -> Self
pub fn of<T: JsonSchema>() -> Self
The schema of a Rust type.
use majordomus_cli::capability::CanonicalSchema;
use schemars::JsonSchema;
/// The thing.
#[derive(JsonSchema)]
struct Thing {
/// A name.
name: String,
count: Option<u32>,
}
let s = CanonicalSchema::of::<Thing>();
assert_eq!(s.name.as_deref(), Some("Thing"));
let (props, required) = s.properties();
assert_eq!(props.iter().map(|(k, _)| k.as_str()).collect::<Vec<_>>(), ["name", "count"]);
assert_eq!(required, ["name"]);Sourcepub fn resolved(&self) -> Cow<'_, CanonicalSchema>
pub fn resolved(&self) -> Cow<'_, CanonicalSchema>
This schema with a root $ref followed into its own $defs: the object the type
describes, rather than the reference that names it.
A #[serde(transparent)] newtype is one shape under two names, and that is how
schemars writes it: the wrapper’s title and description at the root, the shape
under $defs, and nothing but a $ref between them. Every projection that binds
properties — a GET operation’s query parameters, the router’s coercion of the
query string, the Cockpit’s form, the generated module reference — reads the root,
and a root that is a reference has no properties. Unfollowed, the document says the
operation takes nothing while the route still binds every field of the inner
struct, and the router coerces each one against an empty schema: every integer and
boolean parameter then arrives as a string and the call is refused as invalid.
The $defs travel with the resolved schema, so a nested reference still resolves
and for_openapi still hoists every definition.
use majordomus_cli::capability::CanonicalSchema;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
/// What to look for.
#[derive(Serialize, Deserialize, JsonSchema)]
struct SearchInput {
/// The words.
query: String,
/// How many hits at most.
limit: Option<u32>,
}
/// The input of `fixture.search`.
#[derive(Serialize, Deserialize, JsonSchema)]
#[serde(transparent)]
struct Wrapper(SearchInput);
let schema = CanonicalSchema::of::<Wrapper>();
// the wrapper names the component, and its root is a reference
assert_eq!(schema.name.as_deref(), Some("Wrapper"));
assert_eq!(schema.schema["$ref"], "#/$defs/SearchInput");
// and the properties every projection binds are the inner type's
let (properties, required) = schema.properties();
let names: Vec<&str> = properties.iter().map(|(n, _)| n.as_str()).collect();
assert_eq!(names, ["query", "limit"]);
assert_eq!(required, ["query"]);
// a schema whose root is already the object is its own resolution
let plain = CanonicalSchema::of::<SearchInput>();
assert_eq!(plain.resolved().schema, plain.schema);Sourcepub fn properties(&self) -> (Vec<(String, Value)>, Vec<String>)
pub fn properties(&self) -> (Vec<(String, Value)>, Vec<String>)
Top-level properties with their schemas, and which are required, for a schema that
describes an object. Order is the schema’s. A root $ref is followed first, so a
transparent newtype yields the properties of the type it wraps.
Sourcepub fn for_mcp(&self) -> Value
pub fn for_mcp(&self) -> Value
The schema as an MCP client expects it: self-contained, $defs kept inline.
Sourcepub fn for_openapi(
&self,
components: &mut BTreeMap<String, Value>,
) -> Result<Value, String>
pub fn for_openapi( &self, components: &mut BTreeMap<String, Value>, ) -> Result<Value, String>
Split into the top-level schema and its named definitions with every $ref
rewritten to #/components/schemas/<name>, for OpenAPI. A definition name that
is already registered with different content is a conflict, reported by name.
Trait Implementations§
Source§impl Clone for CanonicalSchema
impl Clone for CanonicalSchema
Source§fn clone(&self) -> CanonicalSchema
fn clone(&self) -> CanonicalSchema
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for CanonicalSchema
impl Debug for CanonicalSchema
Source§impl<'de> Deserialize<'de> for CanonicalSchema
impl<'de> Deserialize<'de> for CanonicalSchema
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
impl Eq for CanonicalSchema
Source§impl JsonSchema for CanonicalSchema
impl JsonSchema for CanonicalSchema
Source§fn schema_id() -> Cow<'static, str>
fn schema_id() -> Cow<'static, str>
Source§fn json_schema(generator: &mut SchemaGenerator) -> Schema
fn json_schema(generator: &mut SchemaGenerator) -> Schema
Source§fn inline_schema() -> bool
fn inline_schema() -> bool
$ref keyword. Read moreSource§impl PartialEq for CanonicalSchema
impl PartialEq for CanonicalSchema
Source§fn eq(&self, other: &CanonicalSchema) -> bool
fn eq(&self, other: &CanonicalSchema) -> bool
self and other values to be equal, and is used by ==.Source§impl Serialize for CanonicalSchema
impl Serialize for CanonicalSchema
impl StructuralPartialEq for CanonicalSchema
Auto Trait Implementations§
impl Freeze for CanonicalSchema
impl RefUnwindSafe for CanonicalSchema
impl Send for CanonicalSchema
impl Sync for CanonicalSchema
impl Unpin for CanonicalSchema
impl UnsafeUnpin for CanonicalSchema
impl UnwindSafe for CanonicalSchema
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.