HydraCG / Specifications

Specifications created by the Hydra W3C Community Group
Other
138 stars 26 forks source link

Strongly typed collections in API documentation #233

Open alien-mcl opened 3 years ago

alien-mcl commented 3 years ago

Describe the requirement

I was wondering on how to describe a strongly typed (closed generic) collection in API documentation.

Hydra-agnostic example

There are situations when client could benefit from known in advance what kind of collection members are in the collection. One of the reason would be answer to question "what should I do to obtain a list of users".

Proposed solutions

There are two approaches. One would be to include a piece of a collection mentioned by the API documentation with that documentation itself:

  </api> a hydra:ApiDocumentation;
    hydra:supportedClass api:User.
  hydra:collection </api/users>.
  </api/users> hydra:memberAssertion [
    hydra:predicate rdf:type;
    hydra:object api:User].

This does not require any new terms, but it may be unwanted to mix metadata (an API documentation) with pieces of actual resources. Alternative would be a new term that would allow to more direct and abstract description:

  </api> a hydra:ApiDocumentation;
    hydra:supportedClass api:User;
    api:users </api/users> .
  api:users a hydra:Link;
    hydra:supportedOperation [
      hydra:method "GET";
      hydra:returns [
        rdfs:subClassOf hydra:Collection;
        hydra:memberAssertionEquivalent [
          hydra:predicate rdf:type;
          hydra:object api:User]
      ]
  ] .

The example above introduces a hypothetical hydra:memberAssertionEquivalent term (name is a subject to change). Another alternative would be:

  </api> a hydra:ApiDocumentation;
    hydra:supportedClass api:User;
    api:users </api/users> .
  api:users a hydra:Link;
    hydra:supportedOperation [
      hydra:method "GET";
      hydra:returns hydra:Collection;
      hydra:memberAssertionEquivalent [
          hydra:predicate rdf:type;
          hydra:object api:User]
      ]
  ] .

A brand new term is introduced and attached in a different place (less nesting) compared to the previous example. Slight modification for the two above would require reusing existing hydra:memberAssertion with it's domain modified (currently hydra:Collection). Both of the cases above are abstract descriptions and there are no statements in which the actual resource instance is a subject for.

Feel free to deliberate on the best approach.

tpluscode commented 3 years ago

I like what you write in the last paragraph.

If the domain was changed to loosely allow both Class and Collection

hydra:memberAssertion 
-  rdfs:domain hydra:Collection ;
+  schema:domainIncludes hydra:Class, hydra:Collection ;
.

Then it would be possible to place the assertions on both instances and (sub)class, similarly to what second snippet proposes

api:UserCollection
  rdfs:subClassOf hydra:Collection ;
  hydra:memberAssertion [
    hydra:predicate rdf:type ;
    hydra:object api:User ;
  ] ;
.

</users>
  a api:UserCollection ;
  hydra:memberAssertion [
    hydra:predicate rdf:type ;
    hydra:object api:User ;
  ] ;
.