JSON::Structure Perl SDK
A native Perl implementation of the JSON Structure schema validation system.
Overview
JSON::Structure is a Perl SDK for validating JSON documents against JSON Structure schemas. It provides:
- Schema Validation: Validate that a JSON Structure schema is well-formed
- Instance Validation: Validate JSON data against a JSON Structure schema
- Source Location Tracking: Get line and column numbers for validation errors
- Comprehensive Error Codes: Standardized error codes matching other SDK implementations
Requirements
- Perl 5.20 or later
- JSON::MaybeXS (for transparent JSON::XS acceleration when available)
Installation
From CPAN (when available)
cpanm JSON::Structure
From GitHub
Install directly from GitHub using cpanm:
cpanm git://github.com/json-structure/sdk.git@perl-sdk
From Source
git clone https://github.com/json-structure/sdk.git
cd sdk/perl
perl Makefile.PL
make
make test
make install
Using cpanm with dependencies
cd sdk/perl
cpanm --installdeps .
perl Makefile.PL
make test
Command-Line Interface
The SDK includes pjstruct, a command-line tool for schema and instance validation.
Usage
# Check if a schema is valid
pjstruct check schema.struct.json
# Validate an instance against a schema
pjstruct validate -s schema.struct.json data.json
# Validate multiple files
pjstruct validate -s schema.struct.json *.json
# Output in JSON format
pjstruct validate -s schema.struct.json data.json --format=json
# Output in TAP format (for test harnesses)
pjstruct check *.struct.json --format=tap
# Quiet mode (exit code only)
pjstruct validate -s schema.struct.json data.json -q
Commands
| Command | Alias | Description |
|---------|-------|-------------|
| check | c | Validate schema file(s) against the meta-schema |
| validate | v | Validate instance file(s) against a schema |
| help | | Show help for a command |
| version | | Show version information |
Options
| Option | Short | Description |
|--------|-------|-------------|
| --schema | -s | Schema file (required for validate) |
| --format | -f | Output format: text, json, tap (default: text) |
| --quiet | -q | Suppress output, use exit code only |
| --verbose | -v | Show detailed validation information |
| --help | -h | Show help |
| --version | -V | Show version |
Exit Codes
| Code | Meaning | |------|---------| | 0 | All files are valid | | 1 | One or more files failed validation | | 2 | Error (file not found, parse error, missing options) |
Quick Start
Schema Validation
use JSON::Structure::SchemaValidator;
use JSON::MaybeXS;
# Create a validator
my $validator = JSON::Structure::SchemaValidator->new();
# Parse your schema
my $schema_text = '{"type": "string"}';
my $schema = decode_json($schema_text);
# Validate the schema
my $result = $validator->validate($schema, $schema_text);
if ($result->is_valid) {
print "Schema is valid!\n";
} else {
for my $error (@{$result->errors}) {
printf "Error at %s: %s (code: %s)\n",
$error->path,
$error->message,
$error->code;
}
}
Instance Validation
use JSON::Structure::InstanceValidator;
use JSON::MaybeXS;
# Define your schema
my $schema = {
'$schema' => 'https://json-structure.org/meta/core/v0/#',
'$id' => 'https://example.com/person.struct.json',
name => 'Person',
type => 'object',
properties => {
name => { type => 'string' },
age => { type => 'int32' },
email => { type => 'string' }
},
required => ['name', 'age']
};
# Your data to validate
my $instance = {
name => 'John Doe',
age => 30,
email => 'john@example.com'
};
# Validate
my $validator = JSON::Structure::InstanceValidator->new(schema => $schema);
my $result = $validator->validate($instance);
if ($result->is_valid) {
print "Instance is valid!\n";
} else {
for my $error (@{$result->errors}) {
print "Validation error: " . $error->message . "\n";
}
}
Supported Types
Primitive Types
| Type | Perl Validation |
|------|-----------------|
| string | String value |
| boolean | JSON true/false (JSON::PP::Boolean) |
| int8, int16, int32, int64 | Integer within range |
| uint8, uint16, uint32, uint64 | Unsigned integer within range |
| float32, float64 | Numeric value |
| bytes | Base64-encoded string |
| null | undef or JSON null |
Compound Types
| Type | Description |
|------|-------------|
| object | Object with defined properties |
| array | Homogeneous array of items |
| set | Array with unique items |
| map | Object as string-keyed dictionary |
| tuple | Fixed-length typed array |
| choice | Discriminated union |
| any | Any JSON value |
String Formats
The SDK validates these string formats:
date-time,date,time,durationemail,uri,uri-reference,uuidipv4,ipv6,hostnamejson-pointer,regex
API Reference
JSON::Structure::SchemaValidator
my $validator = JSON::Structure::SchemaValidator->new();
my $result = $validator->validate($schema_doc, $source_text);
new(): Create a new schema validatorvalidate($schema, $source_text): Validate a schema document$schema: Parsed JSON structure (hashref)$source_text: Original JSON text (optional, for location tracking)- Returns:
ValidationResultobject
JSON::Structure::InstanceValidator
my $validator = JSON::Structure::InstanceValidator->new(
schema => $schema,
extended => 1, # Enable extended validation
);
my $result = $validator->validate($instance, $source_text);
new(%options): Create a new instance validatorschema: The JSON Structure schema to validate against (required)extended: Enable extended validation features (minLength, pattern, etc.)allow_import: Enable processing of $import/$importdefsmax_validation_depth: Maximum recursion depth (default: 64)
validate($instance, $source_text): Validate an instance against the schema$instance: Parsed JSON data to validate$source_text: Original JSON text (optional, for location tracking)- Returns:
ValidationResultobject
JSON::Structure::Types
use JSON::Structure::Types qw(ValidationResult ValidationError JsonLocation);
# Create a validation result
my $result = ValidationResult(\@errors, \@warnings);
# Create a validation error
my $error = ValidationError(
code => 'INSTANCE_TYPE_MISMATCH',
message => 'Expected string, got number',
path => '/name',
severity => SEVERITY_ERROR,
location => JsonLocation(line => 1, column => 10),
);
# Check result
if ($result->is_valid) { ... }
for my $err (@{$result->errors}) { ... }
JSON::Structure::ErrorCodes
use JSON::Structure::ErrorCodes qw(:all);
# or import specific groups:
use JSON::Structure::ErrorCodes qw(:schema :instance);
# Available constants:
# Schema errors: SCHEMA_NULL, SCHEMA_INVALID_TYPE, SCHEMA_MISSING_TYPE, etc.
# Instance errors: INSTANCE_TYPE_MISMATCH, INSTANCE_REQUIRED_MEMBER_MISSING, etc.
Error Handling
All validation errors use standardized error codes that are consistent across all JSON Structure SDK implementations:
use JSON::Structure::ErrorCodes qw(:all);
my $result = $validator->validate($schema, $instance);
for my $error (@{$result->errors}) {
if ($error->code eq INSTANCE_TYPE_MISMATCH) {
handle_type_error($error);
}
elsif ($error->code eq INSTANCE_REQUIRED_PROPERTY_MISSING) {
handle_missing_field($error);
}
else {
handle_generic_error($error);
}
}
Source Location Tracking
When you provide the original JSON text, the SDK can report exact line and column numbers for errors:
use JSON::Structure::JsonSourceLocator;
my $locator = JSON::Structure::JsonSourceLocator->new($json_text);
my $location = $locator->get_location('/path/to/element');
printf "Line %d, Column %d\n", $location->line, $location->column;
Testing
# Run all tests
prove -l t/
# Run with verbose output
prove -lv t/
# Run specific test file
prove -l t/02_schema_validator.t
# Run with coverage
cover -test
Publishing to CPAN
See PUBLISHING.md for detailed instructions on publishing to CPAN.
Integration with Test Assets
The SDK can use the shared test assets for cross-SDK compatibility testing:
use File::Spec;
use JSON::PP;
my $assets_dir = File::Spec->catdir('..', 'test-assets');
# Load and run test cases from shared assets
Contributing
See the main SDK-GUIDELINES.md for contribution guidelines and coding standards.
License
MIT License - see LICENSE for details.