Report format¶
validate() and validateAll() resolve to a RunReport. data-standard-validator --format json
prints that same object. The structure is a published contract: within a major
version, fields are only ever added.
interface RunReport {
setup: {
shapes: string[] // where each shapes file came from, in merge order
context?: string // the supplied context, if any
warnings: Issue[] // e.g. an optional shapes file that was not found
}
documents: DocumentReport[]
crossChecks: CrossCheckReport[]
conforms: boolean // every document conforms and every cross-check passed
counts: { violation: number, warning: number, info: number }
}
interface DocumentReport {
document: string // the path, URL or name given
conforms: boolean
counts: { violation: number, warning: number, info: number }
issues: Issue[] // violations first, then by line
}
interface CrossCheckReport {
id: string
title: string
ok: boolean
findings: { message: string, documents: string[] }[]
}
Issues¶
Every issue has two layers. The human layer (title, hint, location,
value, allowedValues) never contains a raw IRI and is safe to show anyone.
The technical layer is for people who know SHACL. It is what makes a bug
report actionable.
interface Issue {
severity: 'violation' | 'warning' | 'info'
code: IssueCode // see error-reference.md
title: string // one line, plain English; may contain `code` and **bold**
hint?: string // what to do about it
location: {
jsonPath: string // `address[0].postcode`, or `$` for the root
pointer: string // RFC 6901: `/address/0/postcode`
nodeType?: string // `@type` as written, e.g. `Address`
nodeId?: string // nearest `@id` the user wrote, on this node or an ancestor
line?: number // 1-based; present when the document was given as text
column?: number
endLine?: number
endColumn?: number
document?: string
}
field?: { term: string, iri: string } // the property, as written and as an IRI
value?: string // the offending value, as the user wrote it
allowedValues?: string[] // for controlled vocabularies, as the tokens to write
technical?: {
focusNode: string // a real IRI, or "(anonymous node at address[0])"
resultPath?: string
sourceShape?: string
constraint: string // e.g. `PatternConstraintComponent`
}
}
Example¶
{
"setup": { "shapes": ["person-shape.ttl"], "warnings": [] },
"documents": [
{
"document": "person.json",
"conforms": false,
"counts": { "violation": 1, "warning": 0, "info": 0 },
"issues": [
{
"severity": "violation",
"code": "value-not-allowed",
"title": "`status` must be one of the permitted values - you gave `ex:Retired`",
"hint": "Allowed values: Active, Inactive.",
"location": {
"jsonPath": "status", "pointer": "/status", "nodeType": "Person",
"line": 5, "column": 13, "endLine": 5, "endColumn": 25, "document": "person.json"
},
"field": { "term": "status", "iri": "https://example.org/status" },
"value": "ex:Retired",
"allowedValues": ["Active", "Inactive"],
"technical": {
"focusNode": "(anonymous node at $)",
"resultPath": "https://example.org/status",
"sourceShape": "n3-2",
"constraint": "InConstraintComponent"
}
}
]
}
],
"crossChecks": [],
"conforms": false,
"counts": { "violation": 1, "warning": 0, "info": 0 }
}