@@ -415,7 +415,7 @@ defmodule OpenApiSpex.Schema do
415
415
end
416
416
end
417
417
418
- @ doc """
418
+ @ doc ~S """
419
419
Validate a value against a Schema.
420
420
421
421
This expects that the value has already been `cast` to the appropriate data type.
@@ -429,17 +429,54 @@ defmodule OpenApiSpex.Schema do
429
429
:ok
430
430
431
431
iex> OpenApiSpex.Schema.validate(%OpenApiSpex.Schema{type: :string, pattern: "(.*)@(.*)"}, "joegmail.com", %{})
432
- {:error, "#: Value does not match pattern: (.*)@(.*)"}
432
+ {:error, "#: Value \" joegmail.com \" does not match pattern: (.*)@(.*)"}
433
433
"""
434
434
@ spec validate ( Schema . t | Reference . t , any , % { String . t => Schema . t | Reference . t } ) :: :ok | { :error , String . t }
435
435
def validate ( schema , val , schemas ) , do: validate ( schema , val , "#" , schemas )
436
436
437
437
@ spec validate ( Schema . t | Reference . t , any , String . t , % { String . t => Schema . t | Reference . t } ) :: :ok | { :error , String . t }
438
438
def validate ( ref = % Reference { } , val , path , schemas ) , do: validate ( Reference . resolve_schema ( ref , schemas ) , val , path , schemas )
439
439
def validate ( % Schema { nullable: true } , nil , _path , _schemas ) , do: :ok
440
- def validate ( % Schema { type: type } , nil , path , _schemas ) do
440
+ def validate ( % Schema { type: type } , nil , path , _schemas ) when not is_nil ( type ) do
441
441
{ :error , "#{ path } : null value where #{ type } expected" }
442
442
end
443
+ def validate ( schema = % Schema { anyOf: valid_schemas } , value , path , schemas ) when is_list ( valid_schemas ) do
444
+ if Enum . any? ( valid_schemas , & validate ( & 1 , value , path , schemas ) == :ok ) do
445
+ validate ( % { schema | anyOf: nil } , value , path , schemas )
446
+ else
447
+ { :error , "#{ path } : Failed to validate against any schema" }
448
+ end
449
+ end
450
+ def validate ( schema = % Schema { oneOf: valid_schemas } , value , path , schemas ) when is_list ( valid_schemas ) do
451
+ case Enum . count ( valid_schemas , & validate ( & 1 , value , path , schemas ) == :ok ) do
452
+ 1 -> validate ( % { schema | oneOf: nil } , value , path , schemas )
453
+ 0 -> { :error , "#{ path } : Failed to validate against any schema" }
454
+ other -> { :error , "#{ path } : Validated against #{ other } schemas when only one expected" }
455
+ end
456
+ end
457
+ def validate ( schema = % Schema { allOf: required_schemas } , value , path , schemas ) when is_list ( required_schemas ) do
458
+ required_schemas
459
+ |> Enum . map ( & validate ( & 1 , value , path , schemas ) )
460
+ |> Enum . reject ( & & 1 == :ok )
461
+ |> Enum . map ( fn { :error , msg } -> msg end )
462
+ |> case do
463
+ [ ] -> validate ( % { schema | allOf: nil } , value , path , schemas )
464
+ errors -> { :error , Enum . join ( errors , "\n " ) }
465
+ end
466
+ end
467
+ def validate ( schema = % Schema { not: not_schema } , value , path , schemas ) when not is_nil ( not_schema ) do
468
+ case validate ( not_schema , value , path , schemas ) do
469
+ { :error , _ } -> validate ( % { schema | not: nil } , value , path , schemas )
470
+ :ok -> { :error , "#{ path } : Value is valid for schema given in `not`" }
471
+ end
472
+ end
473
+ def validate ( % Schema { enum: options = [ _ | _ ] } , value , path , _schemas ) do
474
+ case Enum . member? ( options , value ) do
475
+ true -> :ok
476
+ _ ->
477
+ { :error , "#{ path } : Value not in enum: #{ inspect ( value ) } " }
478
+ end
479
+ end
443
480
def validate ( schema = % Schema { type: :integer } , value , path , _schemas ) when is_integer ( value ) do
444
481
validate_number_types ( schema , value , path )
445
482
end
@@ -480,41 +517,11 @@ defmodule OpenApiSpex.Schema do
480
517
:ok
481
518
end
482
519
end
483
- def validate ( schema = % Schema { anyOf: valid_schemas } , value , path , schemas ) when is_list ( valid_schemas ) do
484
- if Enum . any? ( valid_schemas , & validate ( & 1 , value , path , schemas ) == :ok ) do
485
- validate ( % { schema | anyOf: nil } , value , path , schemas )
486
- else
487
- { :error , "#{ path } : Failed to validate against any schema" }
488
- end
489
- end
490
- def validate ( schema = % Schema { oneOf: valid_schemas } , value , path , schemas ) when is_list ( valid_schemas ) do
491
- case Enum . count ( valid_schemas , & validate ( & 1 , value , path , schemas ) == :ok ) do
492
- 1 -> validate ( % { schema | oneOf: nil } , value , path , schemas )
493
- 0 -> { :error , "#{ path } : Failed to validate against any schema" }
494
- other -> { :error , "#{ path } : Validated against #{ other } schemas when only one expected" }
495
- end
496
- end
497
- def validate ( schema = % Schema { allOf: required_schemas } , value , path , schemas ) when is_list ( required_schemas ) do
498
- required_schemas
499
- |> Enum . map ( & validate ( & 1 , value , path , schemas ) )
500
- |> Enum . reject ( & & 1 == :ok )
501
- |> Enum . map ( fn { :error , msg } -> msg end )
502
- |> case do
503
- [ ] -> validate ( % { schema | allOf: nil } , value , path , schemas )
504
- errors -> { :error , Enum . join ( errors , "\n " ) }
505
- end
506
- end
507
- def validate ( schema = % Schema { not: not_schema } , value , path , schemas ) when not is_nil ( not_schema ) do
508
- case validate ( not_schema , value , path , schemas ) do
509
- { :error , _ } -> validate ( % { schema | not: nil } , value , path , schemas )
510
- :ok -> { :error , "#{ path } : Value is valid for schema given in `not`" }
511
- end
512
- end
513
520
def validate ( % Schema { type: nil } , _value , _path , _schemas ) do
514
521
# polymorphic schemas will terminate here after validating against anyOf/oneOf/allOf/not
515
522
:ok
516
523
end
517
- def validate ( % Schema { type: expected_type } , value , path , _schemas ) do
524
+ def validate ( % Schema { type: expected_type } , value , path , _schemas ) when not is_nil ( expected_type ) do
518
525
{ :error ,
519
526
"#{ path } : invalid type #{ term_type ( value ) } where #{ expected_type } expected" }
520
527
end
@@ -543,7 +550,6 @@ defmodule OpenApiSpex.Schema do
543
550
with :ok <- validate_max_length ( schema , value , path ) ,
544
551
:ok <- validate_min_length ( schema , value , path ) ,
545
552
:ok <- validate_pattern ( schema , value , path ) ,
546
- :ok <- validate_enum ( schema , value , path ) do
547
553
:ok
548
554
end
549
555
end
@@ -593,17 +599,7 @@ defmodule OpenApiSpex.Schema do
593
599
defp validate_pattern ( % { pattern: regex = % Regex { } } , val , path ) do
594
600
case Regex . match? ( regex , val ) do
595
601
true -> :ok
596
- _ -> { :error , "#{ path } : Value does not match pattern: #{ regex . source } " }
597
- end
598
- end
599
-
600
- @ spec validate_enum ( Schema . t , String . t , String . t ) :: :ok | { :error , String . t }
601
- def validate_enum ( % { enum: nil } , _val , _path ) , do: :ok
602
- def validate_enum ( % { enum: options } , value , path ) do
603
- case Enum . member? ( options , value ) do
604
- true -> :ok
605
- _ ->
606
- { :error , "#{ path } : Value not in enum: #{ Enum . join ( options , ", " ) } " }
602
+ _ -> { :error , "#{ path } : Value #{ inspect ( val ) } does not match pattern: #{ regex . source } " }
607
603
end
608
604
end
609
605
0 commit comments