jsonschema-schema 0.2.0

Typed Rust representation of JSON Schema draft 2020-12
Documentation

jsonschema-schema

Crates.io docs.rs GitHub License

Typed Rust structs for JSON Schema (draft 2020-12) documents. Part of the Lintel project.

Unlike raw serde_json::Value, this crate gives you named fields for every standard keyword — properties, items, allOf, $ref, format, and so on — so you can pattern-match and navigate schemas without string lookups.

Features

  • Strongly typedSchema, SchemaValue (object or boolean), TypeValue (single or union), and SimpleType (the seven primitive type names) with full serde round-tripping
  • All standard keywords — core identifiers, metadata, validation, applicators, composition, conditionals, content, and dependencies
  • Editor extensions — first-class x-taplo, x-tombi-*, x-intellij-*, and x-lintel extension structs
  • Catch-all — unknown properties are preserved in extra: BTreeMap<String, Value>
  • Pointer navigationnavigate_pointer walks a JSON Pointer path through nested schemas, resolving $ref along the way
  • Helper utilitiesref_name, resolve_ref, Schema::type_str, Schema::description, and more

Usage

Parsing a schema from JSON

use jsonschema_schema::{Schema, SchemaValue, SimpleType, TypeValue};

let json = serde_json::json!({
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "type": "object",
    "title": "User",
    "properties": {
        "name": { "type": "string" },
        "age": { "type": "integer", "minimum": 0 }
    },
    "required": ["name"]
});

let schema: Schema = serde_json::from_value(json).unwrap();

assert_eq!(schema.title.as_deref(), Some("User"));
assert_eq!(schema.required_set(), &["name"]);

// type_str() produces a human-readable summary
assert_eq!(schema.type_str().as_deref(), Some("object"));

// Access a nested property schema
let name_sv = schema.properties.get("name").unwrap();
let name = name_sv.as_schema().unwrap();
assert!(matches!(name.type_, Some(TypeValue::Single(ref t)) if *t == SimpleType::String));

Building a schema programmatically

use jsonschema_schema::{Schema, SchemaValue, SimpleType, TypeValue};
use indexmap::IndexMap;

let mut props = IndexMap::new();
props.insert("email".to_string(), SchemaValue::Schema(Box::new(Schema {
    type_: Some(TypeValue::Single(SimpleType::String)),
    format: Some("email".into()),
    ..Default::default()
})));

let schema = Schema {
    type_: Some(TypeValue::Single(SimpleType::Object)),
    properties: props,
    required: Some(vec!["email".into()]),
    ..Default::default()
};

let json = serde_json::to_value(&schema).unwrap();
assert_eq!(json["required"], serde_json::json!(["email"]));
assert_eq!(json["properties"]["email"]["format"], "email");

Navigating with JSON Pointers

navigate_pointer resolves a RFC 6901 JSON Pointer through the typed schema tree, automatically following $ref references within the same document.

use jsonschema_schema::{Schema, SchemaValue, SimpleType, TypeValue, navigate_pointer};
use std::collections::BTreeMap;

// Build a schema with $defs and a $ref
let item = SchemaValue::Schema(Box::new(Schema {
    type_: Some(TypeValue::Single(SimpleType::String)),
    ..Default::default()
}));
let mut defs = BTreeMap::new();
defs.insert("Tag".to_string(), item);

let root = SchemaValue::Schema(Box::new(Schema {
    defs: Some(defs),
    ..Default::default()
}));

let result = navigate_pointer(&root, &root, "/$defs/Tag").unwrap();
let tag = result.as_schema().unwrap();
assert_eq!(tag.type_str().as_deref(), Some("string"));

Extracting a ref name

use jsonschema_schema::ref_name;

assert_eq!(ref_name("#/$defs/Address"), "Address");
assert_eq!(ref_name("./other.json"), "other.json");

License

Apache-2.0