- From: Markus Lanthaler <markus.lanthaler@gmx.net>
- Date: Tue, 19 Aug 2014 13:55:31 +0200
- To: <public-hydra@w3.org>
On 19 Aug 2014 at 11:55, Martijn Faassen wrote: > Hey, > > Thanks for the welcome! I hope you'll bear with me; below some of my > lack of experience with JSON-LD will clearly be showing. :) > > On Tue, Aug 19, 2014 at 12:18 AM, Markus Lanthaler > <markus.lanthaler@gmx.net> wrote: >> On 18 Aug 2014 at 10:25, Martijn Faassen wrote: >>> I'm Martijn Faassen, and I've been interested in RESTful APIs for a >>> while. It always bothers me that people can use the word "REST" and >>> ignore links. I work on a Python web framework called Morepath that >>> has more knowledge about linking than usual. I'm considering building >>> a framework on top of it that knows about JSON-LD and Hydra. >> >> Great. If you have a couple of minutes, could you please briefly describe >> in what regards your framework is different from others? > > I have a lot of words here: > > http://morepath.readthedocs.org/en/latest/compared.html > > but that mostly relates to Python web frameworks and it's rather long. Thanks for the pointer. I had a quick look at it. I find the routing idea (bind to models instead of views/controllers) quite interesting. > So briefly: > > I think there are two main points where Morepath is different: > > Lots of built-in facilities for reusing code in various ways; both > fine-grained and course-grained facilities for reusing views and > applications, both by doing inheritance and composition. The main > relevance here would be that you can easily compose JSON in a decoupled > way. ("give me the JSON for this object and put it inside this other > JSON"). That's very interesting for things like collections I guess. > The other difference is that Morepath is a routing framework that can > construct links to objects. > > Morepath is a routing framework, so you can say for a route: > > /issues/{issue_id} > > how that is resolved to a representation, i.e. JSON. > > But while typical routing frameworks do it in one step, that for > instance does a database query for a model, and then create a JSON > representation for that > model all in one function, Morepath breaks this in two functions: > > * getting an object (instance of a model class) for a path > > * making a representation for that object > > This definition structure also allows you to create links to any known > objects by just saying "request.link(model)' without having to know what > the model is or how a path to it is constructed -- that information is > retrieved from the routing information. This allows decoupling and easy > changing of the route map. It also allows the server to very easily > support REST by letting it construct links and send them back. Yeah, I find this idea very interesting. > A nice feature is that Morepath construct URL parameters (?foo=bar) in > links that way as well, so that if you have an object that represents > a query or a batch and you link to it, it can create a link with > parameters in it. > > Sorry for the length, hopefully that was brief enough. :) At least for me, this is highly interesting. Thanks >>> * I myself would've expected a link to the entry point, and this can >>> then contain a reference to the docs. What are the reasons for not >>> having it this way around? >> >> The entry point is an important aspect of an API which means it should >> be included in the documentation. Thus, if we would link to the entry >> point instead of the API Documentation, we would need to define two >> HTTP Link headers: one to point to the entry point and one to point to >> the API documentation. By always pointing to the API documentation we >> just need to define one. What would be improved >> if we would link to the entry point instead? > > I had thought you wouldn't need to define two headers, as you'd get to > the documentation from the entry point itself. But I'm trying to find > that back in the specification, and while it says: > > "Please note that in most cases the entry point will already be known > to the client. Thus, the discovery of the API documentation using HTTP > Link Headers is typically not necessary as the concepts used in > responses from the API will dereference to their documentation." > > I can't find examples of how a response actually points (deferences?) > to its documentation; I only see examples with a context directly It uses the same mechanism as discovery: an HTTP link header. Here are two APIs (loaded in the Hydra API console) that illustrate how it works in practice: http://bit.ly/hydra-console-event-api http://bit.ly/hydra-api-demo > pointing to the hydra vocabulary, not to an application-specific > documentation. I must be missing something or maybe I'm misreading > that line. Yeah, we need to make this clearer in the spec (which isn't up to date at the moment, so please keep that in mind as well). > If I'm not misreading that line, it would be good to follow it up with > an example of how a response in the end points to its documentation. Yep. I've raised ISSUE-68 to track this: https://github.com/HydraCG/Specifications/issues/68 > [alternative kind of batching for collections] >> Yeah, that would be possible as well. We might address this at a >> later point if it turns out to be important. There are multiple ways >> we could address it. > > I think often you'll see collections that support some kind of query > and a kind of batching at the same time. I think it would be useful to > describe such a combined collection. This because my struggles below > show that I actually have no idea how to describe that kind of > collection. :) > > I'd also be interested in seeing examples describing other > interactions with the collection, such as adding. One operation I'm > curious about is 'batch deletion'; deleting multiple items from a > collection is often done more efficiently by sending a whole bunch of > ids directly to the server and having the server delete them as > opposed to issuing multiple delete requests. Though perhaps this isn't > great REST design; I'm not sure. AFAICT, you'd lose the visibility of the DELETE at the HTTP level because you'd have to use a different method (POST). It MAY reduce latency but nothing really prevents you from sending those DELETEs in parallel so I'm not sure how much gain if you really just send IDs. If you want to delete items based on same other criteria (delete all persons older than 18 years), we are talking about something completely different. >>> * in this case it becomes useful for the client to know about what >>> parameters may be sent to control offset and limit. I think this >>> relates to 5.2. It'd be interesting to explore how collections and >>> templated links work together. >> >> Indeed. The most straightforward solution would be to return a >> templated IRI to access a specific page directly. Alternatives would be >> things like a Prefer header (for page size). > > I myself really don't like using headers for this, as it makes it > impossible to pass around a URL to a particular batch (or generate > one, which I'm doing in Morepath). It is possible, but it would be the server's job to tell you the URL instead of having the client to construct those URLs. > I realized that since the structure of the IRIs for id and firstPage > and nextPage are opaque to the client, I can already accomplish > sending back id IRIs with '&offset=10&limit=20' URL parameters instead > of 'page' and still be Hydra. Correct? Right. That's more or less what I meant above. > In relation to this I'm trying to see how I use IRI templates, but I'm > having trouble figuring it out. I can construct something like this: > > { > "@type": "IriTemplate", > "template": "http://api.example.com/an-issue/comment{?page,itemsPerPage}", > ... > } > > I'm at a loss on how I should refer to it. My lack of experience with > JSON-LD is showing. How would I state that a new property > "changePageSize" in Example 14 should be a templated link using this? > Could I also express this about the @id in example 14? You basically have two options. Either you assign that IriTemplate an identifier (@id) that you then use to reference it, or you embed this anonymous node (it's called a blank node) directly as follows: { "@context": "http://www.w3.org/ns/hydra/context.jsonld", "@id": "http://api.example.com/an-issue/comments?page=3", "@type": "PagedCollection", "changePageSize": { "@type": "IriTemplate", "template": "http://api.example.com/an-issue/comment{?page,itemsPerPage}", ... } ... } > If itemsPerPage is not deemed important, I think I'd have the same > issues if I were to combine a (batched) collection with a query API > using URL parameters. Does the above example clarify how it works? > I'm having trouble seeing how example 3 (where a IRI is identified as > a link) fits into a larger example, and I think I need something like > example 3 for a templated link. Example 3 defines the "comments" property used in example 4 (the context maps the term "comments" to the IRI "http://api.example.com/vocab#comments"). For a templated link, you would simply replace "Link" with "TemplatedLink" in example 3 and then set the value of "comments" in example 4 to a IRI template as I did above for "changePageSize". > By the way, how can example 16 be the extracted definition of Hydra's > search property, but the context itself is the hydra vocabulary? Isn't > this definition *part* of the hydra vocabulary? In JSON-LD, the context simply speaking maps terms (short string tokens) to IRIs to make them unambiguous. It can also define prefixes such as "hydra" (mapped to http://www.w3.org/ns/hydra/core#) [1]. That way you can abbreviate IRIs such as http://www.w3.org/ns/hydra/core#search to hydra:search The *definition* of an element, is always in the body of a JSON-LD document. In this case it says that the type of the thing identified with http://www.w3.org/ns/hydra/core#search is http://www.w3.org/ns/hydra/core#TemplatedLink, or, more succinctly, type of hydra:search is hydra:TemplatedLink. This tells a client how to process the hydra:search property (hydra:TemplatedLink is a subclass of rdf:Property [3]). Btw. the full definition of hydra:search can be found at [2] (which is of course served at http://www.w3.org/ns/hydra/core). I hope this helps. If not, please don't hesitate to ask more questions. I'm more than happy to try to answer them. Cheers, Markus [1] https://github.com/HydraCG/Specifications/blob/master/spec/latest/core/core.jsonld#L3 [2] https://github.com/HydraCG/Specifications/blob/master/spec/latest/core/core.jsonld#L395-L402 [3] https://github.com/HydraCG/Specifications/blob/master/spec/latest/core/core.jsonld#L411-L418 -- Markus Lanthaler @markuslanthaler
Received on Tuesday, 19 August 2014 11:56:03 UTC