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.