jsonschema-rs/jsonschema/src/main.rs

88 lines
2.4 KiB
Rust
Raw Normal View History

2022-04-10 21:25:56 +00:00
use std::{
error::Error,
fs::File,
io::BufReader,
path::{Path, PathBuf},
process,
};
2020-10-09 16:28:37 +00:00
use clap::Parser;
2020-10-09 16:28:37 +00:00
use jsonschema::JSONSchema;
type BoxErrorResult<T> = Result<T, Box<dyn Error>>;
#[derive(Parser)]
2022-10-20 14:01:00 +00:00
#[command(name = "jsonschema")]
2020-10-09 16:28:37 +00:00
struct Cli {
/// A path to a JSON instance (i.e. filename.json) to validate (may be specified multiple times).
2022-10-20 14:01:00 +00:00
#[arg(short = 'i', long = "instance")]
2020-10-09 16:28:37 +00:00
instances: Option<Vec<PathBuf>>,
/// The JSON Schema to validate with (i.e. schema.json).
2022-10-20 14:01:00 +00:00
#[arg(value_parser, required_unless_present("version"))]
2020-10-09 16:28:37 +00:00
schema: Option<PathBuf>,
/// Show program's version number and exit.
2022-10-20 14:01:00 +00:00
#[arg(short = 'v', long = "version")]
2020-10-09 16:28:37 +00:00
version: bool,
}
pub fn main() -> BoxErrorResult<()> {
2022-10-20 14:01:00 +00:00
let config = Cli::parse();
2020-10-09 16:28:37 +00:00
if config.version {
println!(concat!("Version: ", env!("CARGO_PKG_VERSION")));
2020-10-09 16:28:37 +00:00
return Ok(());
}
let mut success = true;
if let Some(schema) = config.schema {
if let Some(instances) = config.instances {
success = validate_instances(&instances, schema)?;
}
}
if !success {
process::exit(1);
}
Ok(())
}
2022-01-28 11:13:59 +00:00
fn read_json(path: &Path) -> serde_json::Result<serde_json::Value> {
let file = File::open(path).expect("Failed to open file");
let reader = BufReader::new(file);
serde_json::from_reader(reader)
}
fn validate_instances(instances: &[PathBuf], schema_path: PathBuf) -> BoxErrorResult<bool> {
2020-10-09 16:28:37 +00:00
let mut success = true;
let schema_json = read_json(&schema_path)?;
match JSONSchema::compile(&schema_json) {
Ok(schema) => {
for instance in instances {
let instance_json = read_json(instance)?;
let validation = schema.validate(&instance_json);
let filename = instance.to_string_lossy();
match validation {
Ok(_) => println!("{} - VALID", filename),
Err(errors) => {
success = false;
2020-10-09 16:28:37 +00:00
println!("{} - INVALID. Errors:", filename);
for (i, e) in errors.enumerate() {
println!("{}. {}", i + 1, e);
}
}
2020-10-09 16:28:37 +00:00
}
}
}
Err(error) => {
println!("Schema is invalid. Error: {}", error);
success = false;
}
2020-10-09 16:28:37 +00:00
}
Ok(success)
}