The Schema struct provides JSON Schema-based validation for documents in collections.
Creating a schema
use jasonisnthappy::{Schema, ValueType};
use std::collections::HashMap;
let mut schema = Schema::new();
schema.value_type = Some(ValueType::Object);
Schema fields
Expected type of the value
List of required fields (for objects)
properties
Option<HashMap<String, Schema>>
Schema for object properties
Minimum value for numbers
Maximum value for numbers
Minimum length for strings and arrays
Maximum length for strings and arrays
ValueType enum
Numeric value (integer or float)
Integer value (stricter than Number)
Validation methods
validate
Validate a document against the schema.
pub fn validate(&self, value: &Value) -> Result<()>
Returns: Result<()> - Ok if valid, or Error::SchemaValidation with details
Examples
Basic type validation
use jasonisnthappy::{Schema, ValueType};
use serde_json::json;
let mut schema = Schema::new();
schema.value_type = Some(ValueType::String);
// Valid
assert!(schema.validate(&json!("hello")).is_ok());
// Invalid
assert!(schema.validate(&json!(42)).is_err());
Required fields
let mut schema = Schema::new();
schema.value_type = Some(ValueType::Object);
schema.required = Some(vec!["name".to_string(), "email".to_string()]);
// Valid
let valid_doc = json!({
"name": "Alice",
"email": "alice@example.com"
});
assert!(schema.validate(&valid_doc).is_ok());
// Invalid - missing required field
let invalid_doc = json!({"name": "Alice"});
assert!(schema.validate(&invalid_doc).is_err());
Property validation
use std::collections::HashMap;
let mut schema = Schema::new();
schema.value_type = Some(ValueType::Object);
let mut properties = HashMap::new();
// Name must be a non-empty string
let mut name_schema = Schema::new();
name_schema.value_type = Some(ValueType::String);
name_schema.min_length = Some(1);
properties.insert("name".to_string(), name_schema);
// Age must be a number between 0 and 150
let mut age_schema = Schema::new();
age_schema.value_type = Some(ValueType::Number);
age_schema.minimum = Some(0.0);
age_schema.maximum = Some(150.0);
properties.insert("age".to_string(), age_schema);
schema.properties = Some(properties);
// Valid
let doc = json!({"name": "Alice", "age": 30});
assert!(schema.validate(&doc).is_ok());
// Invalid - age out of range
let doc = json!({"name": "Alice", "age": 200});
assert!(schema.validate(&doc).is_err());
Number validation
let mut schema = Schema::new();
schema.value_type = Some(ValueType::Number);
schema.minimum = Some(0.0);
schema.maximum = Some(100.0);
assert!(schema.validate(&json!(50)).is_ok());
assert!(schema.validate(&json!(-1)).is_err());
assert!(schema.validate(&json!(101)).is_err());
String validation
let mut schema = Schema::new();
schema.value_type = Some(ValueType::String);
schema.min_length = Some(3);
schema.max_length = Some(10);
assert!(schema.validate(&json!("hello")).is_ok());
assert!(schema.validate(&json!("hi")).is_err()); // Too short
assert!(schema.validate(&json!("this is too long")).is_err());
Array validation
let mut schema = Schema::new();
schema.value_type = Some(ValueType::Array);
schema.min_length = Some(1);
schema.max_length = Some(5);
// Items must be numbers
let mut item_schema = Schema::new();
item_schema.value_type = Some(ValueType::Number);
schema.items = Some(Box::new(item_schema));
assert!(schema.validate(&json!([1, 2, 3])).is_ok());
assert!(schema.validate(&json!([])).is_err()); // Too short
assert!(schema.validate(&json!([1, 2, 3, 4, 5, 6])).is_err()); // Too long
assert!(schema.validate(&json!([1, "two", 3])).is_err()); // Wrong item type
Enum validation
let mut schema = Schema::new();
schema.enum_values = Some(vec![
json!("pending"),
json!("active"),
json!("completed"),
]);
assert!(schema.validate(&json!("pending")).is_ok());
assert!(schema.validate(&json!("active")).is_ok());
assert!(schema.validate(&json!("invalid")).is_err());
Integer validation
let mut schema = Schema::new();
schema.value_type = Some(ValueType::Integer);
assert!(schema.validate(&json!(42)).is_ok());
assert!(schema.validate(&json!(-10)).is_ok());
assert!(schema.validate(&json!(3.14)).is_err()); // Not an integer
Nested object validation
use std::collections::HashMap;
let mut schema = Schema::new();
schema.value_type = Some(ValueType::Object);
let mut address_schema = Schema::new();
address_schema.value_type = Some(ValueType::Object);
address_schema.required = Some(vec!["city".to_string()]);
let mut city_schema = Schema::new();
city_schema.value_type = Some(ValueType::String);
let mut address_props = HashMap::new();
address_props.insert("city".to_string(), city_schema);
address_schema.properties = Some(address_props);
let mut properties = HashMap::new();
properties.insert("address".to_string(), address_schema);
schema.properties = Some(properties);
// Valid
let doc = json!({"address": {"city": "NYC"}});
assert!(schema.validate(&doc).is_ok());
// Invalid - missing required nested field
let doc = json!({"address": {}});
assert!(schema.validate(&doc).is_err());
Setting a schema on a collection
use jasonisnthappy::{Database, Schema, ValueType};
use std::collections::HashMap;
let db = Database::open("my.db")?;
let mut schema = Schema::new();
schema.value_type = Some(ValueType::Object);
schema.required = Some(vec!["name".to_string(), "email".to_string()]);
let mut properties = HashMap::new();
let mut name_schema = Schema::new();
name_schema.value_type = Some(ValueType::String);
name_schema.min_length = Some(1);
properties.insert("name".to_string(), name_schema);
let mut email_schema = Schema::new();
email_schema.value_type = Some(ValueType::String);
email_schema.min_length = Some(3);
properties.insert("email".to_string(), email_schema);
schema.properties = Some(properties);
// Set schema on collection
db.set_schema("users", schema)?;
// Now all inserts/updates will be validated
let users = db.collection("users");
// Valid insert
users.insert(json!({
"name": "Alice",
"email": "alice@example.com"
}))?;
// Invalid insert - will fail validation
let result = users.insert(json!({
"name": "Bob"
// Missing required 'email' field
}));
assert!(result.is_err());
Schema serialization
Schemas can be serialized to/from JSON:
use jasonisnthappy::{Schema, ValueType};
let mut schema = Schema::new();
schema.value_type = Some(ValueType::Object);
schema.required = Some(vec!["name".to_string()]);
// Serialize to JSON
let json_str = serde_json::to_string(&schema)?;
// Deserialize from JSON
let deserialized: Schema = serde_json::from_str(&json_str)?;