1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
use crate::gen::{BoolSchemas, SchemaGenerator}; use crate::schema::*; use crate::JsonSchema; macro_rules! map_impl { ($($desc:tt)+) => { impl $($desc)+ where V: JsonSchema, { no_ref_schema!(); fn schema_name() -> String { format!("Map_of_{}", V::schema_name()) } fn json_schema(gen: &mut SchemaGenerator) -> Schema { let subschema = gen.subschema_for::<V>(); let json_schema_bool = gen.settings().bool_schemas == BoolSchemas::AdditionalPropertiesOnly && subschema == gen.schema_for_any(); let additional_properties = if json_schema_bool { true.into() } else { subschema.into() }; SchemaObject { instance_type: Some(InstanceType::Object.into()), object: Some(Box::new(ObjectValidation { additional_properties: Some(Box::new(additional_properties)), ..Default::default() })), ..Default::default() } .into() } } }; } map_impl!(<K, V> JsonSchema for std::collections::BTreeMap<K, V>); map_impl!(<K, V, H> JsonSchema for std::collections::HashMap<K, V, H>); #[cfg(test)] mod tests { use super::*; use crate::gen::*; use crate::tests::{custom_schema_object_for, schema_for}; use pretty_assertions::assert_eq; use std::collections::BTreeMap; #[test] fn schema_for_map_any_value() { for bool_schemas in &[BoolSchemas::Enabled, BoolSchemas::AdditionalPropertiesOnly] { let settings = SchemaSettings::default().with(|s| s.bool_schemas = *bool_schemas); let schema = custom_schema_object_for::<BTreeMap<String, serde_json::Value>>(settings); assert_eq!( schema.instance_type, Some(SingleOrVec::from(InstanceType::Object)) ); let additional_properties = schema .object .unwrap() .additional_properties .expect("additionalProperties field present"); assert_eq!(*additional_properties, Schema::Bool(true)); } } #[test] fn schema_for_map_any_value_no_bool_schema() { let settings = SchemaSettings::default().with(|s| s.bool_schemas = BoolSchemas::Disabled); let schema = custom_schema_object_for::<BTreeMap<String, serde_json::Value>>(settings); assert_eq!( schema.instance_type, Some(SingleOrVec::from(InstanceType::Object)) ); let additional_properties = schema .object .unwrap() .additional_properties .expect("additionalProperties field present"); assert_eq!(*additional_properties, Schema::Object(Default::default())); } #[test] fn schema_for_map_int_value() { for bool_schemas in &[ BoolSchemas::Enabled, BoolSchemas::Disabled, BoolSchemas::AdditionalPropertiesOnly, ] { let settings = SchemaSettings::default().with(|s| s.bool_schemas = *bool_schemas); let schema = custom_schema_object_for::<BTreeMap<String, i32>>(settings); assert_eq!( schema.instance_type, Some(SingleOrVec::from(InstanceType::Object)) ); let additional_properties = schema .object .unwrap() .additional_properties .expect("additionalProperties field present"); assert_eq!(*additional_properties, schema_for::<i32>()); } } }