Integration with SHACL
Introduction
Holger Knublauch has proposed a possible integration path between Hydra and SHACL. Basically, the idea is to make hydra:Class a subclass of sh:Shape.
Hydra uses hydra:Class in several places. One usage is to describe possible request bodies for PUT and POST operations - both in a general ApiDocumentation (hydra:supportedOperation), but also ad-hoc within responses that want to state that a related resource allows a particular operation right now (hydra:operation).
Event Platform API
Let us assume an event platform API wants to describe that its /events resource accepts POST request bodies to create event entries similar to the one below.
// an acceptable POST request body
{
"@context": "http://schema.org",
"@type": "MusicEvent",
"name": "Shostakovich Leningrad",
"startDate": "2016-04-21T20:00"
"location": {
"@type": "MusicVenue",
"name": "Chicago Symphony Center",
"address": {
"streetAddress" : "220 S. Michigan Ave",
"addressLocality" : "Chicago",
"addressRegion" : "IL",
"addressCountry": "USA"
}
}
"eventStatus": "EventScheduled"
}
What makes things interesting is:
- the usage of a vocabulary which is not under control of the service (schema.org). Can we express restrictions on a resource of an externally described class which only apply locally - not only local to an API, but local to a specific expected response?
- the contextual or "nested" schema:name Attribute. We need to say that we expect both a name for the music event *and* the location.
- the dual type of schema:location - it could be a Place or a PostalAddress. Examples on schema.org show that even a plain String might occur.
- the subclassing for the event type: the service wants to say that it accepts many kinds of events, not just MusicEvent. It is however not accepting a DeliveryEvent or a UserInteraction, because these Events are not the kind of Event the platform wants to publish.
- the platform also expects the fixed value "EventScheduled" in a POST, initially it does not allow "EventCancelled" or other values here
Is SHACL able to express all this, and does JSON-LD play along?
{
[...]
"hydra:expects":
{
"@type": "sh:Shape",
"sh:scopeClass": "Event",
"sh:property": [
{
"sh:predicate": "name",
"sh:minCount": 1,
"sh:maxCount": 1
},
{
"sh:predicate": "startDate",
"sh:datatype: "xsd:date"
"sh:minCount": 1,
"sh:maxCount": 1,
"sh:minExclusive": "2015-10-17" <- only future dates
},
{
"sh:predicate": "eventStatus",
"sh:class": "schema:EventStatusType"
"sh:minCount": 1,
"sh:maxCount": 1,
"sh:in" : {
"@list": [
"schema:EventScheduled"
]
}
}
]
}
}
While this might seem quite verbose at first, it is not unlike the way HTML5 describes this sort of information to its generic client, the browser. The big difference to a schema is that we are not describing the conditions of a valid instance of an Event, but the conditions for a request that sends a *new* event to the service.