Schema Validation
Overview
OCPPData.jl includes a runtime validation layer powered by JSONSchema.jl. This lets you validate raw message payloads (as Dict) against the official OCPP JSON schemas before attempting typed deserialization.
This is useful for:
- Validating incoming messages from untrusted charge points
- Providing clear error diagnostics (missing fields, wrong types, invalid enum values)
- Catching malformed messages early in the pipeline
API
validate(spec::AbstractOCPPSpec, action::String, payload::AbstractDict, msg_type::Symbol)| Argument | Values | Example |
|---|---|---|
spec | V16.Spec() or V201.Spec() | V16.Spec() |
action | Action name | "BootNotification" |
payload | Message payload as a Dict | Dict("chargePointVendor" => "V", ...) |
msg_type | :request or :response | :request |
Returns: nothing if valid, or a String describing the validation error.
Examples
using OCPPData, OCPPData.V16, OCPPData.V201Valid Payload
result = validate(
V16.Spec(),
"BootNotification",
Dict("chargePointVendor" => "V", "chargePointModel" => "M"),
:request,
)
isnothing(result)trueMissing Required Field
validate(
V16.Spec(),
"BootNotification",
Dict("chargePointVendor" => "V"),
:request,
)"Validation failed:\npath: top-level\ninstance: Dict(\"chargePointVendor\" => \"V\")\nschema key: required\nschema value: Any[\"chargePointVendor\", \"chargePointModel\"]\n"Wrong Field Type
validate(
V16.Spec(),
"BootNotification",
Dict("chargePointVendor" => 123, "chargePointModel" => "M"),
:request,
)"Validation failed:\npath: [chargePointVendor]\ninstance: 123\nschema key: type\nschema value: string\n"V16 Response Validation
result = validate(
V16.Spec(),
"BootNotification",
Dict(
"status" => "Accepted",
"currentTime" => "2025-01-01T00:00:00Z",
"interval" => 300,
),
:response,
)
isnothing(result)trueV201 Validation
result = validate(
V201.Spec(),
"BootNotification",
Dict(
"reason" => "PowerUp",
"chargingStation" => Dict("model" => "M", "vendorName" => "V"),
),
:request,
)
isnothing(result)trueEmpty Payload (HeartbeatRequest)
result = validate(V16.Spec(), "Heartbeat", Dict{String,Any}(), :request)
isnothing(result)trueHow It Works
Schemas are lazy-loaded and cached on first use. The first call to validate for a given action reads the JSON schema file from disk and compiles it into a JSONSchema.Schema object. Subsequent calls for the same action reuse the cached schema.
Schema files are resolved based on version-specific naming conventions, encoded via multiple dispatch on the Spec type:
- V16:
BootNotification.json(request),BootNotificationResponse.json(response) - V201:
BootNotificationRequest.json,BootNotificationResponse.json