App-jsonvalidate
view release on metacpan or search on metacpan
scripts/jsonvalidate view on Meta::CPAN
# If it's not a proper scheme, treat as relative path
if( $doc_uri !~ /^[a-zA-Z][a-zA-Z0-9+.-]*:/ )
{
my $path = file( $doc_uri, base_dir => $opts->{schema_base} );
if( $path->exists )
{
_message( 6, "Resolver: loading local file $path for $doc_uri" );
return( $path->load_json );
}
}
# Also support explicit file:// URIs
elsif( $doc_uri =~ m{^file://}i )
{
my $path = file( $doc_uri );
if( $path->exists )
{
_message( 6, "Resolver: loading file:// URI $path" );
return( $path->load_json );
}
}
}
# Only if user explicitly asked for remote fetching
# Can also be called as --allow_http. It is aliased to --remote_refs
if( $doc_uri =~ m{^https?://}i )
{
# The specs say that, if there is a fragment, we should always fetch the remote document.
my $should_fetch = $has_fragment || $opts->{remote_refs};
if( $should_fetch )
{
_message( 5, "Resolver: fetching remote document $doc_uri (fragment=$has_fragment, remote-refs=", ( $opts->{remote_refs} // 0 ), ")" );
my $doc = _fetch_http_json( $doc_uri, $json );
return( $doc ) if( defined( $doc ) );
}
else
{
_message( 4, "Resolver: refusing to fetch remote $doc_uri (no fragment and --remote-refs not used)" );
return;
}
}
my $path = file( $doc_uri );
# 4. Last resort: maybe it's a bare filename without base?
if( $path->exists && $path->is_file )
{
_message( 6, "Resolver: fallback loading bare path $path" );
return( $path->load_json );
}
# Fail loudly with helpful message
bailout( <<EOF );
Cannot resolve \$ref "$orig_uri"
Document URI: $doc_uri
Fragment : $fragment
This is probably a fictional/internal \$id (very common and correct!).
The validator will NOT auto-fetch such URIs by default (security + correctness).
This looks like a reference to a remote document with a JSON Pointer fragment.
Such references MUST be retrieved (per JSON Schema spec).
Solutions:
⢠Pass --remote-refs to allow HTTP(S) fetching
⢠Provide the referenced schema via additional --schema arguments
⢠Rewrite the schema to use relative references + --schema-base
EOF
});
# Optional: capture $comment into trace (no-op handler by default)
$js->set_comment_handler(sub{});
# Validate instances
my $total_ok = 0;
my $total_fail = 0;
my $run_idx = 0;
if( $opts->{instance}->is_empty )
{
if( $opts->{jsonl} )
{
_message( 5, "No JSON data file was provided, reading from STDIN line by line." );
while( defined( my $line = <STDIN> ) )
{
next if $line =~ /\A\s*\z/;
my $data = _decode_json_or_die( $line, $json, "STDIN: line $.: " );
_run_one( $js, $data, \$total_ok, \$total_fail, ++$run_idx, $json );
}
}
else
{
_message( 5, "No JSON data file was provided, reading from STDIN all in one go." );
my $data = &_get_stdin();
_run_one( $js, $data, \$total_ok, \$total_fail, ++$run_idx, $json );
}
}
else
{
for my $inst_file ( @{$opts->{instance}} )
{
_message( 5, "Processing JSON data file <green>$inst_file</>" );
if( !$inst_file->exists )
{
bailout( "The instance file \"$inst_file\" does not exist." );
}
elsif( $inst_file->is_empty )
{
_message( 1, "The instance file \"$inst_file\" is empty." );
next;
}
my $raw = $inst_file->load( binmode => 'raw' );
if( !defined( $raw ) )
{
_message( 1, "The instance file \"$inst_file\" content could not be retrieved: ", $inst_file->error );
next;
}
if( $opts->{jsonl} )
{
_message( 5, "Processing the file <green>$inst_file</> data line-by-line." );
( run in 0.511 second using v1.01-cache-2.11-cpan-39bf76dae61 )