Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use serde_json::Value as JsonValue;
use thiserror::Error;

#[derive(Error, Debug, Serialize, Deserialize, Clone, Encode, Decode)]
#[error("JsonSchemaError: keyword: {keyword}, instance_path: {instance_path}, schema_path:{schema_path}")]
#[error("JsonSchemaError: {error_summary}, path: {instance_path}")]
pub struct JsonSchemaError {
/*

Expand All @@ -30,11 +30,12 @@ impl<'a> From<ValidationError<'a>> for JsonSchemaError {
keyword,
params,
property_name,
error_message,
} = JsonSchemaErrorData::from(&validation_error);

Self {
keyword,
error_summary: "".to_string(),
error_summary: error_message,
instance_path: validation_error.instance_path.to_string(),
schema_path: validation_error.schema_path.to_string(),
params: JsonValue::Object(params).into(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use jsonschema::paths::PathChunk;
use jsonschema::ValidationError;
use serde::{Deserialize, Serialize};
use serde_json::Value;
use std::fmt::Write;
use std::ops::Deref;

#[derive(Debug, Serialize, Default, Deserialize)]
Expand All @@ -15,50 +16,55 @@ pub struct JsonSchemaErrorData {
pub keyword: String,
pub params: serde_json::Map<String, Value>,
pub property_name: String,
pub error_message: String,
}

impl<'a> From<&ValidationError<'a>> for JsonSchemaErrorData {
fn from(validation_error: &ValidationError<'a>) -> Self {
let mut error_message = String::new();
let _ = write!(&mut error_message, "{}", validation_error);
let builder = DataBuilder::new().set_error_message(error_message);

match &validation_error.kind {
ValidationErrorKind::Required { property } => DataBuilder::new()
ValidationErrorKind::Required { property } => builder
.set_keyword("required")
.set_property_name(property.to_string())
.add_param("missingProperty", property.clone())
.build(),
ValidationErrorKind::AdditionalItems { limit } => DataBuilder::new()
ValidationErrorKind::AdditionalItems { limit } => builder
.set_keyword("additionalItems")
.add_param("maxItems", Value::from(*limit))
.build(),
ValidationErrorKind::AdditionalProperties { unexpected } => DataBuilder::new()
ValidationErrorKind::AdditionalProperties { unexpected } => builder
.set_keyword("additionalProperties")
.add_param("additionalProperties", unexpected.clone().into())
.build(),
ValidationErrorKind::AnyOf => DataBuilder::new().set_keyword("anyOf").build(),
ValidationErrorKind::BacktrackLimitExceeded { .. } => DataBuilder::new()
.set_keyword("backtrackLimitExceeded")
.build(),
ValidationErrorKind::Constant { expected_value } => DataBuilder::new()
ValidationErrorKind::AnyOf => builder.set_keyword("anyOf").build(),
ValidationErrorKind::BacktrackLimitExceeded { .. } => {
builder.set_keyword("backtrackLimitExceeded").build()
}
ValidationErrorKind::Constant { expected_value } => builder
.set_keyword("const")
.add_param("allowedValue", expected_value.clone())
.build(),
ValidationErrorKind::Contains => DataBuilder::new().set_keyword("contains").build(),
ValidationErrorKind::ContentEncoding { content_encoding } => DataBuilder::new()
ValidationErrorKind::Contains => builder.set_keyword("contains").build(),
ValidationErrorKind::ContentEncoding { content_encoding } => builder
.set_keyword("contentEncoding")
.add_param("contentEncoding", content_encoding.clone().into())
.build(),
ValidationErrorKind::ContentMediaType { content_media_type } => DataBuilder::new()
ValidationErrorKind::ContentMediaType { content_media_type } => builder
.set_keyword("contentMediaType")
.add_param("contentMediaType", content_media_type.clone().into())
.build(),
ValidationErrorKind::Enum { options } => DataBuilder::new()
ValidationErrorKind::Enum { options } => builder
.set_keyword("enum")
.add_param("enum", options.clone())
.build(),
ValidationErrorKind::ExclusiveMaximum { limit } => DataBuilder::new()
ValidationErrorKind::ExclusiveMaximum { limit } => builder
.set_keyword("exclusiveMaximum")
.add_param("exclusiveMaximum", limit.clone())
.build(),
ValidationErrorKind::ExclusiveMinimum { limit } => DataBuilder::new()
ValidationErrorKind::ExclusiveMinimum { limit } => builder
.set_keyword("exclusiveMinimum")
.add_param("exclusiveMinimum", limit.clone())
.build(),
Expand All @@ -69,76 +75,66 @@ impl<'a> From<&ValidationError<'a>> for JsonSchemaErrorData {
_ => "falseSchema",
};

DataBuilder::new().set_keyword(keyword).build()
}
ValidationErrorKind::FileNotFound { .. } => {
DataBuilder::new().set_keyword("fileNotFound").build()
builder.set_keyword(keyword).build()
}
ValidationErrorKind::Format { format } => DataBuilder::new()
ValidationErrorKind::FileNotFound { .. } => builder.set_keyword("fileNotFound").build(),
ValidationErrorKind::Format { format } => builder
.set_keyword("format")
.add_param("format", format.to_string().into())
.build(),
ValidationErrorKind::FromUtf8 { .. } => {
DataBuilder::new().set_keyword("fromUtf8").build()
}
ValidationErrorKind::Utf8 { .. } => DataBuilder::new().set_keyword("utf8").build(),
ValidationErrorKind::JSONParse { .. } => {
DataBuilder::new().set_keyword("JSONParse").build()
}
ValidationErrorKind::InvalidReference { reference } => DataBuilder::new()
ValidationErrorKind::FromUtf8 { .. } => builder.set_keyword("fromUtf8").build(),
ValidationErrorKind::Utf8 { .. } => builder.set_keyword("utf8").build(),
ValidationErrorKind::JSONParse { .. } => builder.set_keyword("JSONParse").build(),
ValidationErrorKind::InvalidReference { reference } => builder
.set_keyword("invalidReference")
.add_param("invalidReference", reference.clone().into())
.build(),
ValidationErrorKind::InvalidURL { .. } => {
DataBuilder::new().set_keyword("invalidURL").build()
}
ValidationErrorKind::MaxItems { limit } => DataBuilder::new()
ValidationErrorKind::InvalidURL { .. } => builder.set_keyword("invalidURL").build(),
ValidationErrorKind::MaxItems { limit } => builder
.set_keyword("maxItems")
.add_param("maxItems", Value::from(*limit))
.build(),
ValidationErrorKind::Maximum { limit } => DataBuilder::new()
ValidationErrorKind::Maximum { limit } => builder
.set_keyword("maximum")
.add_param("maximum", limit.clone())
.build(),
ValidationErrorKind::MaxLength { limit } => DataBuilder::new()
ValidationErrorKind::MaxLength { limit } => builder
.set_keyword("maxLength")
.add_param("maxLength", Value::from(*limit))
.build(),
ValidationErrorKind::MaxProperties { limit } => DataBuilder::new()
ValidationErrorKind::MaxProperties { limit } => builder
.set_keyword("maxProperties")
.add_param("maxProperties", Value::from(*limit))
.build(),
ValidationErrorKind::MinItems { limit } => DataBuilder::new()
ValidationErrorKind::MinItems { limit } => builder
.set_keyword("minItems")
.add_param("minItems", Value::from(*limit))
.build(),
ValidationErrorKind::Minimum { limit } => DataBuilder::new()
ValidationErrorKind::Minimum { limit } => builder
.set_keyword("minimum")
.add_param("minimum", limit.clone())
.build(),
ValidationErrorKind::MinLength { limit } => DataBuilder::new()
ValidationErrorKind::MinLength { limit } => builder
.set_keyword("minLength")
.add_param("minLength", Value::from(*limit))
.build(),
ValidationErrorKind::MinProperties { limit } => DataBuilder::new()
ValidationErrorKind::MinProperties { limit } => builder
.set_keyword("minProperties")
.add_param("minProperties", Value::from(*limit))
.build(),
ValidationErrorKind::MultipleOf { multiple_of } => DataBuilder::new()
ValidationErrorKind::MultipleOf { multiple_of } => builder
.set_keyword("multipleOf")
.add_param("multipleOf", Value::from(*multiple_of))
.build(),
ValidationErrorKind::Not { schema } => DataBuilder::new()
ValidationErrorKind::Not { schema } => builder
.set_keyword("not")
.add_param("not", schema.clone())
.build(),
ValidationErrorKind::OneOfMultipleValid => {
DataBuilder::new().set_keyword("oneOfMultipleValid").build()
builder.set_keyword("oneOfMultipleValid").build()
}
ValidationErrorKind::OneOfNotValid => {
DataBuilder::new().set_keyword("oneOfNotValid").build()
}
ValidationErrorKind::Pattern { pattern } => DataBuilder::new()
ValidationErrorKind::OneOfNotValid => builder.set_keyword("oneOfNotValid").build(),
ValidationErrorKind::Pattern { pattern } => builder
.set_keyword("pattern")
.add_param("pattern", pattern.clone().into())
.build(),
Expand All @@ -147,9 +143,10 @@ impl<'a> From<&ValidationError<'a>> for JsonSchemaErrorData {
keyword,
params,
property_name,
error_message: _,
} = JsonSchemaErrorData::from(error.deref());

DataBuilder::new()
builder
.set_keyword("propertyNames")
.add_param("instancePath", error.instance_path.to_string().into())
.add_param("schemaPath", error.schema_path.to_string().into())
Expand All @@ -159,7 +156,7 @@ impl<'a> From<&ValidationError<'a>> for JsonSchemaErrorData {
.add_param("propertyName", property_name.into())
.build()
}
ValidationErrorKind::Schema => DataBuilder::new().set_keyword("schema").build(),
ValidationErrorKind::Schema => builder.set_keyword("schema").build(),
ValidationErrorKind::Type { kind } => {
let val: Value = match kind {
TypeKind::Single(single) => single.to_string().into(),
Expand All @@ -169,19 +166,14 @@ impl<'a> From<&ValidationError<'a>> for JsonSchemaErrorData {
.collect::<Vec<Value>>()
.into(),
};
DataBuilder::new()
.set_keyword("type")
.add_param("type", val)
.build()
}
ValidationErrorKind::UniqueItems => {
DataBuilder::new().set_keyword("uniqueItems").build()
builder.set_keyword("type").add_param("type", val).build()
}
ValidationErrorKind::UnknownReferenceScheme { scheme } => DataBuilder::new()
ValidationErrorKind::UniqueItems => builder.set_keyword("uniqueItems").build(),
ValidationErrorKind::UnknownReferenceScheme { scheme } => builder
.set_keyword("unknownReferenceScheme")
.add_param("unknownReferenceScheme", scheme.clone().into())
.build(),
ValidationErrorKind::Resolver { url, error: _ } => DataBuilder::new()
ValidationErrorKind::Resolver { url, error: _ } => builder
.set_keyword("resolver")
.add_param("url", url.to_string().into())
.build(),
Expand Down Expand Up @@ -215,6 +207,11 @@ impl DataBuilder {
self
}

fn set_error_message(mut self, message: String) -> Self {
self.data.error_message = message;
self
}

fn build(self) -> JsonSchemaErrorData {
self.data
}
Expand Down