Class: Json::Schema::Diff::SchemaParser

Inherits:
Object
  • Object
show all
Defined in:
lib/json/schema/diff/schema_parser.rb

Overview

Parses and validates JSON Schema files, extracting field metadata for diff guidance

This class handles loading JSON Schema files, validating their structure, and providing methods to extract field information and detect noisy fields.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(schema_file, validate_schema: true) ⇒ SchemaParser

Initialize a new SchemaParser with a JSON Schema file

Raises:

  • (Error)

    If the schema file is invalid or not found



19
20
21
22
23
24
25
26
27
28
29
# File 'lib/json/schema/diff/schema_parser.rb', line 19

def initialize(schema_file, validate_schema: true)
  @schema = JSON.parse(File.read(schema_file))
  
  if validate_schema
    validate_basic_schema_structure!
  end
rescue JSON::ParserError => e
  raise Error, "Invalid JSON schema: #{e.message}"
rescue Errno::ENOENT => e
  raise Error, "Schema file not found: #{e.message}"
end

Instance Attribute Details

#schemaHash (readonly)



12
13
14
# File 'lib/json/schema/diff/schema_parser.rb', line 12

def schema
  @schema
end

Instance Method Details

#get_field_info(path) ⇒ Hash

Gets field information from the schema for a given path



67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/json/schema/diff/schema_parser.rb', line 67

def get_field_info(path)
  field_schema = traverse_schema(path.split('.'))
  return {} unless field_schema

  {
    type: field_schema["type"],
    title: field_schema["title"],
    description: field_schema["description"],
    format: field_schema["format"],
    enum: field_schema["enum"],
    read_only: field_schema["readOnly"] || false
  }
end

#is_noisy_field?(path, value) ⇒ Boolean

Determines if a field is considered “noisy” and should potentially be ignored

Noisy fields are those that change frequently but aren’t meaningful for comparison, such as timestamps, UUIDs, or fields marked as readOnly in the schema.



89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/json/schema/diff/schema_parser.rb', line 89

def is_noisy_field?(path, value)
  field_info = get_field_info(path)
  format = field_info[:format]
  
  # Check for timestamp formats
  return true if format == "date-time" || format == "date" || format == "time"
  
  # Check for UUID format
  return true if format == "uuid"
  
  # Check for fields that look like UUIDs or timestamps
  if value.is_a?(String)
    return true if value.match?(/\A[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\z/i)
    return true if value.match?(/\A\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/)
  end
  
  false
end

#validate_json(json_data) ⇒ Boolean

Validates JSON data against the schema

Performs basic structural validation to ensure JSON data types match schema expectations and required fields are present.

Raises:

  • (Error)

    If validation fails



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/json/schema/diff/schema_parser.rb', line 39

def validate_json(json_data)
  # Simple structural validation - check if JSON structure roughly matches schema expectations
  begin
    # Basic check - if schema has type "array", JSON should be array, etc.
    if @schema["type"] == "array" && !json_data.is_a?(Array)
      raise Error, "JSON validation failed: Expected array but got #{json_data.class.name.downcase}"
    elsif @schema["type"] == "object" && !json_data.is_a?(Hash)
      raise Error, "JSON validation failed: Expected object but got #{json_data.class.name.downcase}"
    end
    
    # If we have required fields in schema, check they exist in JSON
    if @schema["required"] && json_data.is_a?(Hash)
      missing_fields = @schema["required"] - json_data.keys
      unless missing_fields.empty?
        raise Error, "JSON validation failed: Missing required fields: #{missing_fields.join(', ')}"
      end
    end
    
    true
  rescue StandardError => e
    raise Error, "JSON validation error: #{e.message}"
  end
end