resthttpjson-ldhypermediahydra-core

Get a collection of sub-resources at once with JSON-LD and Hydra


In the RESTful Web API book, the authors advise to expose a profile and use a content type which acknowledges link relations. JSON-LD extended by Hydra seem to match these requirements, and I want to use them in the design of my new API.

I am currently stuck with a performance issue. Let say that I have an online bike store, and I want to retrieve information about the wheels of a given bike.

With the Hydra specification, it seems to me that I need to send 2 requests to get the details about the wheels. The first request is toward the bike itself:

GET /mybike HTTP/1.1
Host: wowbike.com

The response contains a Hydra::Link to the collection of wheels:

HTTP/1.1 200 OK
Content-Type: application/ld+json
{
  "@context" :
               {
                   "Bike": "/contexts/vocab#Bike"
               },
  "@id"      : "/mybike",
  "@type"    : "Bike",
  "size"     : "L",
  "wheels"   : "/mybike/wheels" // "wheels" is a "hydra:Link"
}

Now I can send a second request to the wheels resource to get the details:

GET /mybike/wheels HTTP/1.1
Host: wowbike.com

HTTP/1.1 200 OK
Content-Type: application/ld+json
{
    "@context":
               {
                   "Collection": "http://www.w3.org/ns/hydra/core#Collection",
                   "Wheel"     : "/contexts/vocab#Wheel"
               },
    "@type"   : "Collection",
    "@id"     : "/mybike/wheels",
    "member"  :
                [
                 {
                   "@id"   : "/mybike/wheels/firstwheel",
                   "@type" : "Wheel",
                   "color" : "blue"
                 },
                 {
                   "@id"   : "/mybike/wheels/secondwheel",
                   "@type" : "Wheel",
                   "color" : "white"
                 }
                ]
}

Is it valid to send a single request and get a response such as the one below?

GET /mybike HTTP/1.1
Host: wowbike.com

HTTP/1.1 200 OK
Content-Type: application/ld+json
{
  "@context" : 
               {
                   "Collection": "http://www.w3.org/ns/hydra/core#Collection",
                   "Bike"      : "/contexts/vocab#Bike",
                   "Wheel"     : "/contexts/vocab#Wheel"
               },
  "@id"      : "/mybike",
  "@type"    : "Bike",
  "size"     : "L",
  "wheels"   :
               {
                  "@id"   : "/mybike/wheels",
                  "@type" : "Link",
                  "member":
                            [
                             {
                               "@id"   : "/mybike/wheels/firstwheel",
                               "@type" : "Wheel",
                               "color" : "blue"
                             },
                             {
                               "@id"   : "/mybike/wheels/secondwheel",
                               "@type" : "Wheel",
                               "color" : "white"
                             }
                            ]
               }

}

Solution

  • Great to see that you consider using JSON-LD and Hydra. Of course it is possible to get all the data in a single response. You don't have to change the type of the collection from Collection to Link though. Also, you might want to tweak your context a bit. Summed up, your response would look somewhat like this:

    {
      "@context": [
        "http://www.w3.org/ns/hydra/context.jsonld",
        { "@vocab": "/contexts/vocab#" }
      ],
      "@id": "/mybike",
      "@type": "Bike",
      "size": "L",
      "wheels": {
        "@id"   : "/mybike/wheels",
        "@type" : "Collection",
        "member": [
          {
            "@id"   : "/mybike/wheels/firstwheel",
            "@type" : "Wheel",
            "color" : "blue"
          },
          {
            "@id"   : "/mybike/wheels/secondwheel",
            "@type" : "Wheel",
            "color" : "white"
          }
        ]
      }
    }
    

    I'm importing Hydra's context here and then overlaying a default vocabulary which means that everything that isn't already defined in Hydra's context is expanded by appending it to /contexts/vocab#. So, Bike for instance will be expanded to /contexts/vocab#Bike.

    Btw. there's a W3C Community Groupw working on Hydra which you should join if you are using it. We also have a mailing list on which all your questions will be answered.

    The instructions to join the group can be found at http://www.hydra-cg.com/#community