OpenAPI and JSON Schema

vld-schemars

Two-way bridge between vld and schemars - vld types as schemars::JsonSchema, and schemars types validated through vld.

Many crates (aide, okapi, paperclip, …) consume schemars::JsonSchema. vld-schemars connects them to vld in both directions:

  • vld → schemars: impl_json_schema!(T) implements schemars::JsonSchema from the vld json_schema().
  • schemars → vld: impl_vld_parse!(T) validates a #[derive(JsonSchema)] type against its schemars schema and implements vld::schema::VldParse, so it works with vld web extractors.

Install

Cargo.toml
[dependencies]
vld = { version = "0.5", features = ["openapi"] }
vld-schemars = "0.5"   # schemars 0.9-0.x (default)

schemars 1.x:

Cargo.toml
[dependencies]
vld-schemars = { version = "0.5", default-features = false, features = ["schemars-1"] }

Features

FeatureDefaultDescription
schemars-0yesschemars >=0.9, <1
schemars-1noschemars >=1, <2

Enable exactly one. The selected crate is re-exported as vld_schemars::schemars; derive with vld_schemars::schemars::JsonSchema to be sure the versions match.

MSRV: 1.85 for both features (see MSRV).

Example

use vld_schemars::prelude::*;
use vld_schemars::schemars;

// vld -> schemars
vld::schema! {
    #[derive(Debug)]
    pub struct UserSchema {
        pub name: String  => vld::string().min(2).max(100),
        pub email: String => vld::string().email(),
        pub age: i64      => vld::number().int().min(0).max(150),
    }
}
impl_json_schema!(UserSchema);

let mut gen = schemars::SchemaGenerator::default();
let schema = <UserSchema as schemars::JsonSchema>::json_schema(&mut gen);
assert_eq!(schema.as_value()["properties"]["email"]["format"], "email");

// schemars -> vld
#[derive(Debug, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
struct Product {
    name: String,
    price: f64,
}
impl_vld_parse!(Product);

let json = serde_json::json!({"name": "Widget", "price": 9.99});
let product = Product::vld_parse(&json).unwrap();       // validate + deserialize
assert!(product.vld_validate().is_ok());                 // validate an instance
assert!(Product::vld_validate_json(&serde_json::json!({"name": 1})).is_err());

API

ItemDescription
impl_json_schema!(T) / impl_json_schema!(T, "Name")schemars::JsonSchema for a vld type; nested types are added to the generator's definitions
impl_vld_parse!(T)VldParse + SchemarsValidate for a schemars type
SchemarsValidatevld_validate(&self), vld_validate_json(&Value), vld_parse(&Value)
vld_to_schemars(&Value)JSON Schema value → schemars::Schema (a non-schema value becomes false)
try_vld_to_schemars(&Value)Same, returns an error for a non-schema value
vld_schema_to_schemars(&Value)Alias of vld_to_schemars for a json_schema() result
schemars_to_json, generate_from_schemars::<T>(), generate_schemars::<T>()schemars → serde_json::Value / root schema
validate_with_schema(&schema, &value) / validate_with_schemarsValidate JSON against a JSON Schema, issues as VldError
to_openapi3(&mut Value)Rewrite vld's 2020-12 output into the OpenAPI 3.0 dialect
list_properties, list_properties_schemars, PropertyInfo, schema_type, is_required, get_propertyIntrospection helpers
schemas_equal, merge_schemas, overlay_constraintsCompare / combine schemas
VldSchemarsErrorValidation(VldError) or Deserialization(String)

Gotchas

  • impl_json_schema! rewrites vld's #/components/schemas/X refs to the generator's definitions path (#/$defs/X by default, #/components/schemas/X under SchemaSettings::openapi3()).
  • With an OpenAPI 3.0 generator (SchemaSettings::openapi3()) the output is converted by to_openapi3: tuples become items: {anyOf: [...]}, null branches become nullable: true, numeric exclusive bounds use the boolean 3.0 form.
  • The built-in validator (validate_with_schema, impl_vld_parse!) covers types, required fields, length / numeric / array / object constraints, enum, composites, patternProperties, prefixItems and local $refs. It does not check vld's x-* keywords (x-past, x-minUniqueItems, …) and most formats beyond a basic shape check. Validate with the vld schema itself when those matter.
  • impl_vld_parse! regenerates the schemars schema on every call. Cache the schema yourself on hot paths.

See also vld-aide and JSON Schema.