JSON-Validator

 view release on metacpan or  search on metacpan

Changes  view on Meta::CPAN

   Contributor: Henrik Andersen

5.17 2026-06-04T22:32:00
 - Add validate Mojo::Upload as binary string in OpenAPIv3 #288
   Contributor: Archey Barrell

5.16 2026-06-04T10:06:00
 - Use Mojo::File::spew instead of Mojo::File::spurt #281
   Contributor: Emmanuel Seyman
 - Updated dependency list #283
 - Use negotiated content-type to select schema #289
   Contributor: Archey Barrell
 - Updated idn-email format verification to allow periods in local part #290
   Contributor: Keith Carangelo
 - Add string as valid format #293

5.15 2025-03-16T18:47:47
 - Make JSON::Validator::Util::is_bool return true when passed perl v5.36+ builtin booleans #275
 - Fix wrong resolving of responses component using $ref #277
 - Fix array coercion for array parameters with a $ref schema #274

Changes  view on Meta::CPAN

 - Removed support for subclassing JSON::Validator. Need to subclass a schema
   class instead.
 - Simpler inheritance for Schema classes

4.19 2021-06-17T12:37:10+0900
 - Fix generating correct base_url() object with host and port

4.18 2021-06-17T11:13:58+0900
 - Fix content_type validation for OpenAPIv2 and OpenAPIv3
 - Fix validating multipart\/form-data with boundary
 - Fix validating content-type with charset
 - Fix parsing OpenAPIv3 spec with "description", "servers" and "summary" in a
   path specifiation.

4.17 2021-04-28T11:30:56+0900
 - Add add_default_response() to OpenAPIv2 and OpenAPIv3
 - Add base_url() to OpenAPIv2 and OpenAPIv3
 - Fix validating "nullable" for "array" and "object"

4.16 2021-03-24T08:57:46+0900
 - Fix handling OpenAPIv2 "responses" $ref when bundling

MANIFEST  view on Meta::CPAN

t/openapiv2-collection-format.t
t/openapiv2-default-values.t
t/openapiv2-discriminator.t
t/openapiv2-file.t
t/openapiv2-headers.t
t/openapiv2-readonly.t
t/openapiv2-routes.t
t/openapiv3-basic.t
t/openapiv3-bundled-spec.t
t/openapiv3-coerce-array.t
t/openapiv3-content-types.t
t/openapiv3-default-values.t
t/openapiv3-discriminator.t
t/openapiv3-file.t
t/openapiv3-nullable.t
t/openapiv3-readonly-writeonly.t
t/openapiv3-style-explode.t
t/predictable-errors.t
t/random-errors.t
t/recursive_data_protection.t
t/relative-ref.t

lib/JSON/Validator/Schema/OpenAPIv3.pm  view on Meta::CPAN

  if (@{$param->{accepts}} and $val->{content_type}) {
    $negotiated_content_type = negotiate_content_type($param->{accepts}, $val->{content_type});
    $val->{valid} = $negotiated_content_type ? 1 : 0;
    return E "/$param->{name}", [join(', ', @{$param->{accepts}}) => type => $val->{content_type}] unless $negotiated_content_type;
  }
  if ($param->{required} and !$val->{exists}) {
    $val->{valid} = 0;
    return E "/$param->{name}", [qw(object required)];
  }
  if ($val->{exists}) {
    # Ensures we have a valid content-type so we can select a schema
    # This can happen if the negotiation fails (e.g. content-type is empty)
    $negotiated_content_type //= $param->{accepts}[0];

    # Mutate request content-type if one was not set
    $val->{content_type} //= $negotiated_content_type;

    local $self->{coerce}{arrays} = 1
      if $val->{content_type} =~ m!^(application/x-www-form-urlencoded|multipart/form-data)\s*(;|$)!;

    local $self->{"validate_$direction"} = 1;

    my $body_params = $param->{content}{$negotiated_content_type};
    my @errors = map { $_->path(_prefix_error_path($param->{name}, $_->path)); $_ }
      $self->validate($val->{value}, $body_params->{schema});

t/openapiv3-content-types.t  view on Meta::CPAN

use Mojo::Base -strict;
use JSON::Validator;
use Test::More;

my $schema = JSON::Validator->new->schema('data://main/spec.yaml')->schema;
my ($body, @errors);

sub body {$body}

subtest '*/* w/ required body' => sub {
  subtest 'content-type is missing' => sub {
    $body = {exists => 0};
    @errors = $schema->validate_request([post => '/pets_any'], {body => \&body});
    is "@errors", "/body: Missing property.", 'invalid request body';

    $body = {exists => 1, value => {name => 'kitty'}};
    @errors = $schema->validate_request([post => '/pets_any'], {body => \&body});
    is "@errors", "", 'valid request body';

    $body = {exists => 1, value => {age => 42}};
    @errors = $schema->validate_request([post => '/pets_any'], {body => \&body});
    is "@errors", "/body/name: Missing property.", 'invalid request body';
  };

  subtest 'content-type is empty string' => sub {
    $body = {exists => 0, content_type => ''};
    @errors = $schema->validate_request([post => '/pets_any'], {body => \&body});
    is "@errors", "/body: Missing property.", 'invalid request body';

    $body = {exists => 1, value => {name => 'kitty'}, content_type => ''};
    @errors = $schema->validate_request([post => '/pets_any'], {body => \&body});
    is "@errors", "", 'valid request body';

    $body = {exists => 1, value => {age => 42}, content_type => ''};
    @errors = $schema->validate_request([post => '/pets_any'], {body => \&body});
    is "@errors", "/body/name: Missing property.", 'invalid request body';
  };

  subtest 'content-type is application/json' => sub {
    $body = {exists => 0};
    @errors = $schema->validate_request([post => '/pets_any'], {body => \&body});
    is "@errors", "/body: Missing property.", 'invalid request body';

    $body = {exists => 1, value => {name => 'kitty'}, content_type => 'application/json'};
    @errors = $schema->validate_request([post => '/pets_any'], {body => \&body});
    is "@errors", "", 'valid request body';

    $body = {exists => 1, value => {age => 42}, content_type => 'application/json'};
    @errors = $schema->validate_request([post => '/pets_any'], {body => \&body});
    is "@errors", "/body/name: Missing property.", 'invalid request body';
  };

  subtest 'content-type is application/json; charset=utf-8' => sub {
    $body = {exists => 0};
    @errors = $schema->validate_request([post => '/pets_any'], {body => \&body});
    is "@errors", "/body: Missing property.", 'invalid request body';

    $body = {exists => 1, value => {name => 'kitty'}, content_type => 'application/json; charset=utf-8'};
    @errors = $schema->validate_request([post => '/pets_any'], {body => \&body});
    is "@errors", "", 'valid request body';

    $body = {exists => 1, value => {age => 42}, content_type => 'application/json; charset=utf-8'};
    @errors = $schema->validate_request([post => '/pets_any'], {body => \&body});
    is "@errors", "/body/name: Missing property.", 'invalid request body';
  };
};

subtest 'application/json w/ body' => sub {
  subtest 'content-type is missing' => sub {
    $body = {exists => 0};
    @errors = $schema->validate_request([post => '/pets_json'], {body => \&body});
    is "@errors", "/body: Missing property.", 'invalid request body';

    $body = {exists => 1, value => {name => 'kitty'}};
    @errors = $schema->validate_request([post => '/pets_json'], {body => \&body});
    is "@errors", "", 'valid request body';

    $body = {exists => 1, value => {age => 42}};
    @errors = $schema->validate_request([post => '/pets_any'], {body => \&body});
    is "@errors", "/body/name: Missing property.", 'invalid request body';
  };

  subtest 'content-type is empty string' => sub {
    $body = {exists => 0, content_type => ''};
    @errors = $schema->validate_request([post => '/pets_json'], {body => \&body});
    is "@errors", "/body: Missing property.", 'invalid request body';

    $body = {exists => 1, value => {name => 'kitty'}, content_type => ''};
    @errors = $schema->validate_request([post => '/pets_json'], {body => \&body});
    is "@errors", "", 'valid request body';

    $body = {exists => 1, value => {age => 42}, content_type => ''};
    @errors = $schema->validate_request([post => '/pets_any'], {body => \&body});
    is "@errors", "/body/name: Missing property.", 'invalid request body';
  };

  subtest 'content-type is application/json' => sub {
    $body = {exists => 0};
    @errors = $schema->validate_request([post => '/pets_json'], {body => \&body});
    is "@errors", "/body: Missing property.", 'invalid request body';

    $body = {exists => 1, value => {name => 'kitty'}, content_type => 'application/json'};
    @errors = $schema->validate_request([post => '/pets_json'], {body => \&body});
    is "@errors", "", 'valid request body';

    $body = {exists => 1, value => {age => 42}, content_type => 'application/json'};
    @errors = $schema->validate_request([post => '/pets_json'], {body => \&body});
    is "@errors", "/body/name: Missing property.", 'invalid request body';
  };

  subtest 'content-type is application/json; charset=utf-8' => sub {
    $body = {exists => 1, value => {name => 'kitty'}, content_type => 'application/json; charset=utf-8'};
    @errors = $schema->validate_request([post => '/pets_json'], {body => \&body});
    is "@errors", "", 'valid request body';

    $body = {exists => 1, value => {age => 42}, content_type => 'application/json; charset=utf-8'};
    @errors = $schema->validate_request([post => '/pets_json'], {body => \&body});
    is "@errors", "/body/name: Missing property.", 'invalid request body';
  };

  subtest 'content-type is application/xml' => sub {
    $body = {exists => 0, content_type => 'application/xml'};
    @errors = $schema->validate_request([post => '/pets_json'], {body => \&body});
    is "@errors", "/body: Expected application/json - got application/xml.", 'invalid request body';

    $body = {exists => 1, value => {name => 'kitty'}, content_type => 'application/xml'};
    @errors = $schema->validate_request([post => '/pets_json'], {body => \&body});
    is "@errors", "/body: Expected application/json - got application/xml.", 'invalid request body';

    $body = {exists => 1, value => {age => 42}, content_type => 'application/xml'};
    @errors = $schema->validate_request([post => '/pets_json'], {body => \&body});



( run in 1.478 second using v1.01-cache-2.11-cpan-d7f47b0818f )