Class: Cocina::Models::Validators::JsonSchemaValidator

Inherits:
Object
  • Object
show all
Defined in:
lib/cocina/models/validators/json_schema_validator.rb

Overview

Validates Cocina model instances against the JSON schema.

The schema uses OpenAPI 3.1.0 conventions with ‘unevaluatedProperties: false` to enforce strict validation. However, when schemas use `allOf` with `$ref` (which is common for composing mixins), json_schemer reports cascaded unevaluatedProperties errors that are not actionable.

For example, if a schema has:

AdminPolicy:
  allOf:
    - $ref: '#/$defs/AdminPolicyMixin'   # defines properties
  unevaluatedProperties: false

And an unexpected property appears at ‘/administrative/releaseTags`, json_schemer will report both:

- The actual error at `/administrative/releaseTags` (actionable)
- Cascaded errors for every known root property like `/label`, `/type` (noise)

This happens because ‘unevaluatedProperties` semantics with `allOf`/$ref can be ambiguous. See github.com/davishmcclurg/json_schemer/issues/157

To reduce noise while preserving actionable errors, this validator applies de-noising by keeping only:

1. All errors for nested properties (depth > 1)
2. Root-level errors for genuinely unknown properties (not in the model schema)

This filters out cascaded root-level false positives without hiding real nested issues.

Constant Summary collapse

SCHEMA_PATH =
::File.expand_path('../../../../schema.json', __dir__)

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(clazz, attributes) ⇒ JsonSchemaValidator

Returns a new instance of JsonSchemaValidator.

Parameters:

  • clazz (Class)

    the Cocina model class being validated (e.g., Cocina::Models::DRO)

  • attributes (Hash)

    the attributes of the model instance being validated



52
53
54
55
# File 'lib/cocina/models/validators/json_schema_validator.rb', line 52

def initialize(clazz, attributes)
  @clazz = clazz
  @attributes = attributes
end

Class Method Details

.documentHash

Returns a hash representation of the schema.json document.

Returns:

  • (Hash)

    a hash representation of the schema.json document



43
44
45
46
47
48
# File 'lib/cocina/models/validators/json_schema_validator.rb', line 43

def self.document
  @document ||= begin
    file_content = ::File.read(SCHEMA_PATH)
    JSON.parse(file_content)
  end
end

.validateObject

See Also:



38
39
40
# File 'lib/cocina/models/validators/json_schema_validator.rb', line 38

def self.validate(...)
  new(...).validate
end

Instance Method Details

#validateNilClass

Validates attributes against the Cocina model schema.

Injects the cocinaVersion if the model includes it as an attribute, then validates the attributes against the schema definition for this model. De-noises unevaluatedProperties errors before raising a ValidationError.

Returns:

  • (NilClass)

    returns nil if validation passes

Raises:

  • (ValidationError)

    if validation fails, with a de-noised error message



65
66
67
68
69
70
71
72
# File 'lib/cocina/models/validators/json_schema_validator.rb', line 65

def validate
  attributes['cocinaVersion'] = Cocina::Models::VERSION if clazz.attribute_names.include?(:cocinaVersion)

  errors = schema.ref("#/$defs/#{method_name}").validate(attributes.as_json).to_a
  return if errors.empty?

  raise ValidationError, "When validating #{method_name}: " + filtered_error_messages(errors).join(', ')
end