Add Schema
methods insert
, get
and remove
These are just convenience methods that delegate to the inner object. `insert` will also convert bool schemas to object schemas.
This commit is contained in:
parent
d6c8b6b022
commit
0672c862c8
7 changed files with 109 additions and 76 deletions
|
@ -129,9 +129,7 @@ pub struct MyTransform;
|
||||||
impl Transform for MyTransform {
|
impl Transform for MyTransform {
|
||||||
fn transform(&mut self, schema: &mut Schema) {
|
fn transform(&mut self, schema: &mut Schema) {
|
||||||
// First, make our change to this schema
|
// First, make our change to this schema
|
||||||
if let Some(obj) = schema.as_object_mut() {
|
schema.insert("my_property".to_string(), serde_json::json!("hello world"));
|
||||||
obj.insert("my_property".to_string(), serde_json::json!("hello world"));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Then apply the transform to any subschemas
|
// Then apply the transform to any subschemas
|
||||||
transform_subschemas(self, schema);
|
transform_subschemas(self, schema);
|
||||||
|
@ -147,9 +145,7 @@ Also, since `Transform` is now implemented for functions that take a single `&mu
|
||||||
```rust
|
```rust
|
||||||
fn my_transform(schema: &mut Schema) {
|
fn my_transform(schema: &mut Schema) {
|
||||||
// First, make our change to this schema
|
// First, make our change to this schema
|
||||||
if let Some(obj) = schema.as_object_mut() {
|
schema.insert("my_property".to_string(), serde_json::json!("hello world"));
|
||||||
obj.insert("my_property".to_string(), serde_json::json!("hello world"));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Then apply the transform to any subschemas
|
// Then apply the transform to any subschemas
|
||||||
transform_subschemas(&mut my_transform, schema);
|
transform_subschemas(&mut my_transform, schema);
|
||||||
|
@ -165,9 +161,7 @@ Finally, you can also use the `RecursiveTransform` newtype to convert a non-recu
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
fn my_transform2(schema: &mut Schema) {
|
fn my_transform2(schema: &mut Schema) {
|
||||||
if let Some(obj) = schema.as_object_mut() {
|
schema.insert("my_property".to_string(), serde_json::json!("hello world"));
|
||||||
obj.insert("my_property".to_string(), serde_json::json!("hello world"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut schema = schemars::schema_for!(str);
|
let mut schema = schemars::schema_for!(str);
|
||||||
|
|
|
@ -25,9 +25,7 @@ pub enum MyEnum {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_format(schema: &mut Schema) {
|
fn remove_format(schema: &mut Schema) {
|
||||||
if let Some(obj) = schema.as_object_mut() {
|
schema.remove("format");
|
||||||
obj.remove("format");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
|
@ -25,9 +25,7 @@ pub enum MyEnum {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_format(schema: &mut Schema) {
|
fn remove_format(schema: &mut Schema) {
|
||||||
if let Some(obj) = schema.as_object_mut() {
|
schema.remove("format");
|
||||||
obj.remove("format");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
|
@ -20,9 +20,7 @@ pub fn json_schema_for_flatten<T: ?Sized + JsonSchema>(
|
||||||
let mut schema = T::_schemars_private_non_optional_json_schema(generator);
|
let mut schema = T::_schemars_private_non_optional_json_schema(generator);
|
||||||
|
|
||||||
if T::_schemars_private_is_option() && !required {
|
if T::_schemars_private_is_option() && !required {
|
||||||
if let Some(object) = schema.as_object_mut() {
|
schema.remove("required");
|
||||||
object.remove("required");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Always allow aditional/unevaluated properties, because the outer struct determines
|
// Always allow aditional/unevaluated properties, because the outer struct determines
|
||||||
|
@ -33,16 +31,14 @@ pub fn json_schema_for_flatten<T: ?Sized + JsonSchema>(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn allow_unknown_properties(schema: &mut Schema) {
|
fn allow_unknown_properties(schema: &mut Schema) {
|
||||||
if let Some(obj) = schema.as_object_mut() {
|
if schema.get("additionalProperties").and_then(Value::as_bool) == Some(false) {
|
||||||
if obj.get("additionalProperties").and_then(Value::as_bool) == Some(false) {
|
schema.remove("additionalProperties");
|
||||||
obj.remove("additionalProperties");
|
|
||||||
}
|
|
||||||
if obj.get("unevaluatedProperties").and_then(Value::as_bool) == Some(false) {
|
|
||||||
obj.remove("unevaluatedProperties");
|
|
||||||
}
|
|
||||||
|
|
||||||
transform_immediate_subschemas(&mut allow_unknown_properties, schema);
|
|
||||||
}
|
}
|
||||||
|
if schema.get("unevaluatedProperties").and_then(Value::as_bool) == Some(false) {
|
||||||
|
schema.remove("unevaluatedProperties");
|
||||||
|
}
|
||||||
|
|
||||||
|
transform_immediate_subschemas(&mut allow_unknown_properties, schema);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Hack to simulate specialization:
|
/// Hack to simulate specialization:
|
||||||
|
@ -211,7 +207,7 @@ pub fn apply_inner_validation(schema: &mut Schema, f: fn(&mut Schema) -> ()) {
|
||||||
if let Some(inner_schema) = schema
|
if let Some(inner_schema) = schema
|
||||||
.as_object_mut()
|
.as_object_mut()
|
||||||
.and_then(|o| o.get_mut("items"))
|
.and_then(|o| o.get_mut("items"))
|
||||||
.and_then(|i| <&mut Schema>::try_from(i).ok())
|
.and_then(|i| i.try_into().ok())
|
||||||
{
|
{
|
||||||
f(inner_schema);
|
f(inner_schema);
|
||||||
}
|
}
|
||||||
|
|
|
@ -138,10 +138,80 @@ impl Schema {
|
||||||
self.0 = Value::Object(map);
|
self.0 = Value::Object(map);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.as_object_mut()
|
self.0
|
||||||
|
.as_object_mut()
|
||||||
.expect("Schema value should be of type Object.")
|
.expect("Schema value should be of type Object.")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Inserts a property into the schema, replacing any previous value.
|
||||||
|
///
|
||||||
|
/// If the schema wraps a bool value, it will first be converted into an equivalent object schema.
|
||||||
|
///
|
||||||
|
/// If the schema did not have this key present, `None` is returned.
|
||||||
|
///
|
||||||
|
/// If the schema did have this key present, the value is updated, and the old value is returned.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
/// ```
|
||||||
|
/// use schemars::json_schema;
|
||||||
|
/// use serde_json::json;
|
||||||
|
///
|
||||||
|
/// let mut schema = json_schema!(true);
|
||||||
|
/// assert_eq!(schema.insert("type".to_owned(), "array".into()), None);
|
||||||
|
/// assert_eq!(schema.insert("type".to_owned(), "object".into()), Some(json!("array")));
|
||||||
|
///
|
||||||
|
/// assert_eq!(schema, json_schema!({"type": "object"}));
|
||||||
|
/// ```
|
||||||
|
pub fn insert(&mut self, k: String, v: Value) -> Option<Value> {
|
||||||
|
self.ensure_object().insert(k, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// If the `Schema`'s underlying JSON value is an object, gets a reference to that object's value for the given key.
|
||||||
|
///
|
||||||
|
/// This always returns `None` for bool schemas.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
/// ```
|
||||||
|
/// use schemars::json_schema;
|
||||||
|
/// use serde_json::json;
|
||||||
|
///
|
||||||
|
/// let obj_schema = json_schema!({"type": "array"});
|
||||||
|
/// assert_eq!(obj_schema.get("type"), Some(&json!("array")));
|
||||||
|
/// assert_eq!(obj_schema.get("format"), None);
|
||||||
|
///
|
||||||
|
/// let bool_schema = json_schema!(true);
|
||||||
|
/// assert_eq!(bool_schema.get("type"), None);
|
||||||
|
/// ```
|
||||||
|
pub fn get<Q>(&self, key: &Q) -> Option<&Value>
|
||||||
|
where
|
||||||
|
String: core::borrow::Borrow<Q>,
|
||||||
|
Q: ?Sized + Ord + Eq + core::hash::Hash,
|
||||||
|
{
|
||||||
|
self.0.as_object().and_then(|o| o.get(key))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// If the `Schema`'s underlying JSON value is an object, removes and returns its value for the given key.
|
||||||
|
///
|
||||||
|
/// This always returns `None` for bool schemas, without modifying them.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
/// ```
|
||||||
|
/// use schemars::json_schema;
|
||||||
|
/// use serde_json::json;
|
||||||
|
///
|
||||||
|
/// let mut schema = json_schema!({"type": "array"});
|
||||||
|
/// assert_eq!(schema.remove("type"), Some(json!("array")));
|
||||||
|
/// assert_eq!(schema, json_schema!({}));
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
pub fn remove<Q>(&mut self, key: &Q) -> Option<Value>
|
||||||
|
where
|
||||||
|
String: core::borrow::Borrow<Q>,
|
||||||
|
Q: ?Sized + Ord + Eq + core::hash::Hash,
|
||||||
|
{
|
||||||
|
self.0.as_object_mut().and_then(|o| o.remove(key))
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn has_type(&self, ty: &str) -> bool {
|
pub(crate) fn has_type(&self, ty: &str) -> bool {
|
||||||
match self.0.get("type") {
|
match self.0.get("type") {
|
||||||
Some(Value::Array(values)) => values.iter().any(|v| v.as_str() == Some(ty)),
|
Some(Value::Array(values)) => values.iter().any(|v| v.as_str() == Some(ty)),
|
||||||
|
|
|
@ -21,9 +21,7 @@ pub struct MyTransform;
|
||||||
impl Transform for MyTransform {
|
impl Transform for MyTransform {
|
||||||
fn transform(&mut self, schema: &mut Schema) {
|
fn transform(&mut self, schema: &mut Schema) {
|
||||||
// First, make our change to this schema
|
// First, make our change to this schema
|
||||||
if let Some(obj) = schema.as_object_mut() {
|
schema.insert("my_property".to_string(), "hello world".into());
|
||||||
obj.insert("my_property".to_string(), serde_json::json!("hello world"));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Then apply the transform to any subschemas
|
// Then apply the transform to any subschemas
|
||||||
transform_subschemas(self, schema);
|
transform_subschemas(self, schema);
|
||||||
|
@ -55,9 +53,7 @@ The same example with a `fn` transform:
|
||||||
use schemars::transform::transform_subschemas;
|
use schemars::transform::transform_subschemas;
|
||||||
|
|
||||||
fn add_property(schema: &mut Schema) {
|
fn add_property(schema: &mut Schema) {
|
||||||
if let Some(obj) = schema.as_object_mut() {
|
schema.insert("my_property".to_string(), "hello world".into());
|
||||||
obj.insert("my_property".to_string(), serde_json::json!("hello world"));
|
|
||||||
}
|
|
||||||
|
|
||||||
transform_subschemas(&mut add_property, schema)
|
transform_subschemas(&mut add_property, schema)
|
||||||
}
|
}
|
||||||
|
@ -87,9 +83,7 @@ And the same example using a closure wrapped in a `RecursiveTransform`:
|
||||||
use schemars::transform::{Transform, RecursiveTransform};
|
use schemars::transform::{Transform, RecursiveTransform};
|
||||||
|
|
||||||
let mut transform = RecursiveTransform(|schema: &mut Schema| {
|
let mut transform = RecursiveTransform(|schema: &mut Schema| {
|
||||||
if let Some(obj) = schema.as_object_mut() {
|
schema.insert("my_property".to_string(), "hello world".into());
|
||||||
obj.insert("my_property".to_string(), serde_json::json!("hello world"));
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
let mut schema = json_schema!({
|
let mut schema = json_schema!({
|
||||||
|
@ -236,9 +230,7 @@ pub(crate) fn transform_immediate_subschemas<T: Transform + ?Sized>(
|
||||||
/// use schemars::transform::{Transform, RecursiveTransform};
|
/// use schemars::transform::{Transform, RecursiveTransform};
|
||||||
///
|
///
|
||||||
/// let mut transform = RecursiveTransform(|schema: &mut Schema| {
|
/// let mut transform = RecursiveTransform(|schema: &mut Schema| {
|
||||||
/// if let Some(obj) = schema.as_object_mut() {
|
/// schema.insert("my_property".to_string(), "hello world".into());
|
||||||
/// obj.insert("my_property".to_string(), serde_json::json!("hello world"));
|
|
||||||
/// }
|
|
||||||
/// });
|
/// });
|
||||||
///
|
///
|
||||||
/// let mut schema = json_schema!({
|
/// let mut schema = json_schema!({
|
||||||
|
@ -289,9 +281,7 @@ impl Transform for ReplaceBoolSchemas {
|
||||||
if let Some((ap_key, ap_value)) = obj.remove_entry("additionalProperties") {
|
if let Some((ap_key, ap_value)) = obj.remove_entry("additionalProperties") {
|
||||||
transform_subschemas(self, schema);
|
transform_subschemas(self, schema);
|
||||||
|
|
||||||
if let Some(obj) = schema.as_object_mut() {
|
schema.insert(ap_key, ap_value);
|
||||||
obj.insert(ap_key, ap_value);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -339,11 +329,9 @@ impl Transform for SetSingleExample {
|
||||||
fn transform(&mut self, schema: &mut Schema) {
|
fn transform(&mut self, schema: &mut Schema) {
|
||||||
transform_subschemas(self, schema);
|
transform_subschemas(self, schema);
|
||||||
|
|
||||||
if let Some(obj) = schema.as_object_mut() {
|
if let Some(Value::Array(examples)) = schema.remove("examples") {
|
||||||
if let Some(Value::Array(examples)) = obj.remove("examples") {
|
if let Some(first_example) = examples.into_iter().next() {
|
||||||
if let Some(first_example) = examples.into_iter().next() {
|
schema.insert("example".into(), first_example);
|
||||||
obj.insert("example".into(), first_example);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -360,10 +348,8 @@ impl Transform for ReplaceConstValue {
|
||||||
fn transform(&mut self, schema: &mut Schema) {
|
fn transform(&mut self, schema: &mut Schema) {
|
||||||
transform_subschemas(self, schema);
|
transform_subschemas(self, schema);
|
||||||
|
|
||||||
if let Some(obj) = schema.as_object_mut() {
|
if let Some(value) = schema.remove("const") {
|
||||||
if let Some(value) = obj.remove("const") {
|
schema.insert("enum".into(), Value::Array(vec![value]));
|
||||||
obj.insert("enum".into(), Value::Array(vec![value]));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -381,13 +367,11 @@ impl Transform for ReplacePrefixItems {
|
||||||
fn transform(&mut self, schema: &mut Schema) {
|
fn transform(&mut self, schema: &mut Schema) {
|
||||||
transform_subschemas(self, schema);
|
transform_subschemas(self, schema);
|
||||||
|
|
||||||
if let Some(obj) = schema.as_object_mut() {
|
if let Some(prefix_items) = schema.remove("prefixItems") {
|
||||||
if let Some(prefix_items) = obj.remove("prefixItems") {
|
let previous_items = schema.insert("items".to_owned(), prefix_items);
|
||||||
let previous_items = obj.insert("items".to_owned(), prefix_items);
|
|
||||||
|
|
||||||
if let Some(previous_items) = previous_items {
|
if let Some(previous_items) = previous_items {
|
||||||
obj.insert("additionalItems".to_owned(), previous_items);
|
schema.insert("additionalItems".to_owned(), previous_items);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -400,14 +384,11 @@ impl Transform for ReplaceUnevaluatedProperties {
|
||||||
fn transform(&mut self, schema: &mut Schema) {
|
fn transform(&mut self, schema: &mut Schema) {
|
||||||
transform_subschemas(self, schema);
|
transform_subschemas(self, schema);
|
||||||
|
|
||||||
let Some(obj) = schema.as_object_mut() else {
|
let Some(up) = schema.remove("unevaluatedProperties") else {
|
||||||
return;
|
|
||||||
};
|
|
||||||
let Some(up) = obj.remove("unevaluatedProperties") else {
|
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
obj.insert("additionalProperties".to_owned(), up);
|
schema.insert("additionalProperties".to_owned(), up);
|
||||||
|
|
||||||
let mut gather_property_names = GatherPropertyNames::default();
|
let mut gather_property_names = GatherPropertyNames::default();
|
||||||
gather_property_names.transform(schema);
|
gather_property_names.transform(schema);
|
||||||
|
|
|
@ -1,24 +1,20 @@
|
||||||
mod util;
|
mod util;
|
||||||
use schemars::{transform::RecursiveTransform, JsonSchema, Schema};
|
use schemars::{transform::RecursiveTransform, JsonSchema, Schema};
|
||||||
use serde_json::Value;
|
use serde_json::{Map, Value};
|
||||||
use util::*;
|
use util::*;
|
||||||
|
|
||||||
fn capitalize_type(schema: &mut Schema) {
|
fn capitalize_type(schema: &mut Schema) {
|
||||||
if let Some(obj) = schema.as_object_mut() {
|
if let Some(Value::String(ty)) = schema.get("type") {
|
||||||
if let Some(Value::String(ty)) = obj.get("type") {
|
schema.insert("upperType".to_owned(), ty.to_uppercase().into());
|
||||||
obj.insert("upperType".to_owned(), ty.to_uppercase().into());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn insert_property_count(schema: &mut Schema) {
|
fn insert_property_count(schema: &mut Schema) {
|
||||||
if let Some(obj) = schema.as_object_mut() {
|
let count = schema
|
||||||
let count = obj
|
.get("properties")
|
||||||
.get("properties")
|
.and_then(Value::as_object)
|
||||||
.and_then(|p| p.as_object())
|
.map_or(0, Map::len);
|
||||||
.map_or(0, |p| p.len());
|
schema.insert("propertyCount".to_owned(), count.into());
|
||||||
obj.insert("propertyCount".to_owned(), count.into());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue