diff --git a/errors/validation_error.go b/errors/validation_error.go index 4c590ae..5c83a6d 100644 --- a/errors/validation_error.go +++ b/errors/validation_error.go @@ -9,29 +9,29 @@ import ( "github.com/santhosh-tekuri/jsonschema/v6" ) -// SchemaValidationFailure is a wrapper around the jsonschema.ValidationError object, to provide a more -// user-friendly way to break down what went wrong. +// SchemaValidationFailure describes any failure that occurs when validating data +// against either an OpenAPI or JSON Schema. It aims to be a more user-friendly +// representation of the error than what is provided by the jsonschema library. type SchemaValidationFailure struct { // Reason is a human-readable message describing the reason for the error. Reason string `json:"reason,omitempty" yaml:"reason,omitempty"` - // Location is the XPath-like location of the validation failure - Location string `json:"location,omitempty" yaml:"location,omitempty"` + // InstancePath is the raw path segments from the root to the failing field + InstancePath []string `json:"instancePath,omitempty" yaml:"instancePath,omitempty"` // FieldName is the name of the specific field that failed validation (last segment of the path) FieldName string `json:"fieldName,omitempty" yaml:"fieldName,omitempty"` - // FieldPath is the JSONPath representation of the field location (e.g., "$.user.email") + // FieldPath is the JSONPath representation of the field location that failed validation (e.g., "$.user.email") FieldPath string `json:"fieldPath,omitempty" yaml:"fieldPath,omitempty"` - // InstancePath is the raw path segments from the root to the failing field - InstancePath []string `json:"instancePath,omitempty" yaml:"instancePath,omitempty"` - - // DeepLocation is the path to the validation failure as exposed by the jsonschema library. - DeepLocation string `json:"deepLocation,omitempty" yaml:"deepLocation,omitempty"` + // KeywordLocation is the relative path to the JsonSchema keyword that failed validation + // This will be empty if the validation failure did not originate from JSON Schema validation + KeywordLocation string `json:"keywordLocation,omitempty" yaml:"keywordLocation,omitempty"` - // AbsoluteLocation is the absolute path to the validation failure as exposed by the jsonschema library. - AbsoluteLocation string `json:"absoluteLocation,omitempty" yaml:"absoluteLocation,omitempty"` + // AbsoluteKeywordLocation is the absolute path to the validation failure as exposed by the jsonschema library. + // This will be empty if the validation failure did not originate from JSON Schema validation + AbsoluteKeywordLocation string `json:"absoluteKeywordLocation,omitempty" yaml:"absoluteKeywordLocation,omitempty"` // Line is the line number where the violation occurred. This may a local line number // if the validation is a schema (only schemas are validated locally, so the line number will be relative to @@ -46,14 +46,18 @@ type SchemaValidationFailure struct { // ReferenceSchema is the schema that was referenced in the validation failure. ReferenceSchema string `json:"referenceSchema,omitempty" yaml:"referenceSchema,omitempty"` - // ReferenceObject is the object that was referenced in the validation failure. + // ReferenceObject is the object that failed schema validation ReferenceObject string `json:"referenceObject,omitempty" yaml:"referenceObject,omitempty"` // ReferenceExample is an example object generated from the schema that was referenced in the validation failure. ReferenceExample string `json:"referenceExample,omitempty" yaml:"referenceExample,omitempty"` - // The original error object, which is a jsonschema.ValidationError object. - OriginalError *jsonschema.ValidationError `json:"-" yaml:"-"` + // The original jsonschema.ValidationError object, if the schema failure originated from the jsonschema library. + OriginalJsonSchemaError *jsonschema.ValidationError `json:"-" yaml:"-"` + + // DEPRECATED in favor of explicit use of FieldPath & InstancePath + // Location is the XPath-like location of the validation failure + Location string `json:"location,omitempty" yaml:"location,omitempty"` } // Error returns a string representation of the error @@ -97,7 +101,7 @@ type ValidationError struct { ParameterName string `json:"parameterName,omitempty" yaml:"parameterName,omitempty"` // SchemaValidationErrors is a slice of SchemaValidationFailure objects that describe the validation errors - // This is only populated whe the validation type is against a schema. + // This is only populated when the validation type is against a schema. SchemaValidationErrors []*SchemaValidationFailure `json:"validationErrors,omitempty" yaml:"validationErrors,omitempty"` // Context is the object that the validation error occurred on. This is usually a pointer to a schema diff --git a/parameters/validate_parameter.go b/parameters/validate_parameter.go index 12dbd83..d9914ca 100644 --- a/parameters/validate_parameter.go +++ b/parameters/validate_parameter.go @@ -226,12 +226,12 @@ func formatJsonSchemaValidationError(schema *base.Schema, scErrs *jsonschema.Val } fail := &errors.SchemaValidationFailure{ - Reason: errMsg, - Location: er.KeywordLocation, - FieldName: helpers.ExtractFieldNameFromStringLocation(er.InstanceLocation), - FieldPath: helpers.ExtractJSONPathFromStringLocation(er.InstanceLocation), - InstancePath: helpers.ConvertStringLocationToPathSegments(er.InstanceLocation), - OriginalError: scErrs, + Reason: errMsg, + Location: er.KeywordLocation, + FieldName: helpers.ExtractFieldNameFromStringLocation(er.InstanceLocation), + FieldPath: helpers.ExtractJSONPathFromStringLocation(er.InstanceLocation), + InstancePath: helpers.ConvertStringLocationToPathSegments(er.InstanceLocation), + OriginalJsonSchemaError: scErrs, } if schema != nil { rendered, err := schema.RenderInline() diff --git a/requests/validate_request.go b/requests/validate_request.go index 64550cb..f6f6aac 100644 --- a/requests/validate_request.go +++ b/requests/validate_request.go @@ -167,14 +167,14 @@ func ValidateRequestSchema( errMsg := er.Error.Kind.LocalizedString(message.NewPrinter(language.Tag{})) violation := &errors.SchemaValidationFailure{ - Reason: errMsg, - Location: er.KeywordLocation, - FieldName: helpers.ExtractFieldNameFromStringLocation(er.InstanceLocation), - FieldPath: helpers.ExtractJSONPathFromStringLocation(er.InstanceLocation), - InstancePath: helpers.ConvertStringLocationToPathSegments(er.InstanceLocation), - ReferenceSchema: string(renderedSchema), - ReferenceObject: referenceObject, - OriginalError: jk, + Reason: errMsg, + Location: er.KeywordLocation, + FieldName: helpers.ExtractFieldNameFromStringLocation(er.InstanceLocation), + FieldPath: helpers.ExtractJSONPathFromStringLocation(er.InstanceLocation), + InstancePath: helpers.ConvertStringLocationToPathSegments(er.InstanceLocation), + ReferenceSchema: string(renderedSchema), + ReferenceObject: referenceObject, + OriginalJsonSchemaError: jk, } // if we have a location within the schema, add it to the error if located != nil { diff --git a/responses/validate_response.go b/responses/validate_response.go index 7011533..865ddb5 100644 --- a/responses/validate_response.go +++ b/responses/validate_response.go @@ -194,14 +194,14 @@ func ValidateResponseSchema( } violation := &errors.SchemaValidationFailure{ - Reason: errMsg, - Location: er.KeywordLocation, - FieldName: helpers.ExtractFieldNameFromStringLocation(er.InstanceLocation), - FieldPath: helpers.ExtractJSONPathFromStringLocation(er.InstanceLocation), - InstancePath: helpers.ConvertStringLocationToPathSegments(er.InstanceLocation), - ReferenceSchema: string(renderedSchema), - ReferenceObject: referenceObject, - OriginalError: jk, + Reason: errMsg, + Location: er.KeywordLocation, + FieldName: helpers.ExtractFieldNameFromStringLocation(er.InstanceLocation), + FieldPath: helpers.ExtractJSONPathFromStringLocation(er.InstanceLocation), + InstancePath: helpers.ConvertStringLocationToPathSegments(er.InstanceLocation), + ReferenceSchema: string(renderedSchema), + ReferenceObject: referenceObject, + OriginalJsonSchemaError: jk, } // if we have a location within the schema, add it to the error if located != nil { diff --git a/schema_validation/validate_document.go b/schema_validation/validate_document.go index 42d198e..d17cf0e 100644 --- a/schema_validation/validate_document.go +++ b/schema_validation/validate_document.go @@ -84,14 +84,14 @@ func ValidateOpenAPIDocument(doc libopenapi.Document, opts ...config.Option) (bo // locate the violated property in the schema located := LocateSchemaPropertyNodeByJSONPath(info.RootNode.Content[0], er.InstanceLocation) violation := &liberrors.SchemaValidationFailure{ - Reason: errMsg, - Location: er.InstanceLocation, - FieldName: helpers.ExtractFieldNameFromStringLocation(er.InstanceLocation), - FieldPath: helpers.ExtractJSONPathFromStringLocation(er.InstanceLocation), - InstancePath: helpers.ConvertStringLocationToPathSegments(er.InstanceLocation), - DeepLocation: er.KeywordLocation, - AbsoluteLocation: er.AbsoluteKeywordLocation, - OriginalError: jk, + Reason: errMsg, + Location: er.InstanceLocation, + FieldName: helpers.ExtractFieldNameFromStringLocation(er.InstanceLocation), + FieldPath: helpers.ExtractJSONPathFromStringLocation(er.InstanceLocation), + InstancePath: helpers.ConvertStringLocationToPathSegments(er.InstanceLocation), + KeywordLocation: er.KeywordLocation, + AbsoluteKeywordLocation: er.AbsoluteKeywordLocation, + OriginalJsonSchemaError: jk, } // if we have a location within the schema, add it to the error diff --git a/schema_validation/validate_schema.go b/schema_validation/validate_schema.go index 4d1c67a..f20b92b 100644 --- a/schema_validation/validate_schema.go +++ b/schema_validation/validate_schema.go @@ -300,16 +300,16 @@ func extractBasicErrors(schFlatErrs []jsonschema.OutputUnit, } violation := &liberrors.SchemaValidationFailure{ - Reason: errMsg, - Location: er.InstanceLocation, - FieldName: helpers.ExtractFieldNameFromStringLocation(er.InstanceLocation), - FieldPath: helpers.ExtractJSONPathFromStringLocation(er.InstanceLocation), - InstancePath: helpers.ConvertStringLocationToPathSegments(er.InstanceLocation), - DeepLocation: er.KeywordLocation, - AbsoluteLocation: er.AbsoluteKeywordLocation, - ReferenceSchema: string(renderedSchema), - ReferenceObject: referenceObject, - OriginalError: jk, + Reason: errMsg, + Location: er.InstanceLocation, + FieldName: helpers.ExtractFieldNameFromStringLocation(er.InstanceLocation), + FieldPath: helpers.ExtractJSONPathFromStringLocation(er.InstanceLocation), + InstancePath: helpers.ConvertStringLocationToPathSegments(er.InstanceLocation), + KeywordLocation: er.KeywordLocation, + AbsoluteKeywordLocation: er.AbsoluteKeywordLocation, + ReferenceSchema: string(renderedSchema), + ReferenceObject: referenceObject, + OriginalJsonSchemaError: jk, } // if we have a location within the schema, add it to the error if located != nil {