Hi,I am pretty new to the json schema topics, and try to get my head around how to define link relationships within json instances.What I understood so far, is schemas allow to define and document the link relationships, including the query parameters (properties of link description).Where I struggle is how to remain HATEOS with consumers, which is my understanding only the producer should generate links, the client should only consume them (so if the server decides to change the link structure, it won't break client). Concept of URI opacity etc.
But when you say "the producer should generate links, the client should only consume them" - which side of that do JSON Hyper-Schemas fit in? In general, the producer of the data is also the producer of the schemas, so the link definitions in the schema can still be considered as "coming from the server".The power of hyper-schemas is that the client can take *all* of its cues from the server. Don't stop at URI opacity - if the producer wants to change the name of the variable that the link URI is stored in, they just change the link definition in the schema - a flexibly-coded client won't even blink.
Phil
Thanks David for the follow up. It is still not clear to me1) Do you agree with my understanding, that for remaining HATEOS (hypermedia driven) server serving a resource should include links in the data representation of that resource (or as Link Header if you want to keep that distinct from the data)? I believe you agree since you wrote "the flexibility of [links] comes from the fact that the URI for the link can be extracted from the instance data."2) If you agree with 1), and assuming we do prefer making this part of data instead of Link headers, then shouldn't my "properties" section of my schema - using hyper schema, as per previous example - include an array of links?
On Thursday, January 31, 2013 5:08:49 PM UTC, Philippe Marsteau wrote:Thanks David for the follow up. It is still not clear to me1) Do you agree with my understanding, that for remaining HATEOS (hypermedia driven) server serving a resource should include links in the data representation of that resource (or as Link Header if you want to keep that distinct from the data)? I believe you agree since you wrote "the flexibility of [links] comes from the fact that the URI for the link can be extracted from the instance data."2) If you agree with 1), and assuming we do prefer making this part of data instead of Link headers, then shouldn't my "properties" section of my schema - using hyper schema, as per previous example - include an array of links?
If the links are themselves completely unpredictable (not just the URI, but unpredictable link relation, target media type, and title) - then yes. A property in the data called "links", holding an array of Link Description Objects, is the best thing to do. At that point, you no longer need to define the links in the schema - you just describe the "links" property exactly as you did in your first example, and that's all you need to do.
--
You received this message because you are subscribed to the Google Groups "JSON Schema" group.
To unsubscribe from this group and stop receiving emails from it, send an email to json-schema...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
If the intent of hyperschemas to let consumers build URIs themselves (using URI templates) then I believe we are fundamentally breaking the hypermedia constraint of REST. Even if a consumer is downloading the schema on each call (to get aware of URI structure changes), it would still need out of band information (coupling) as of the core part of the href (excluding the templating). That core part could change (e.g. depending on call origin, I may generate a different root href part to target the "closest" location to caller). Having that core part known to client is creating coupling unless you convey the information on each call (as part of the json instance). I agree that if I did not had that requirement of changing core part of the URI (say it would be root URI all times), I could have consumer building the other part of the "href" (using URI templating).
Now considering my use case, I do see value of hyperschema - as long as the only part consumers build is the query string part (for GET) or the forms properties (PUT/POST) a user should know to send data (using known properties, known encoding, and known link relations provided by the schema).What's wrong with not letting consumers build the "href" at all, and letting it be truly opaque to consumer? What's wrong with having server being the only one to know which links are indeed available or not? Because your schema documents _all_ links, it does not tell under which conditions these are available or not. As an example, a pagination "next" or "prev" link should not be always available depending which page is retrieved from the collection.
The consumer _having knowledge of the schema_ would know:
- The relation ID and media types to lookup in the json instance (now they get the server-generated "href" value). If link is not present, consumers knows it cannot follow the link.
- The link properties (GET or POST) needed to send data to the API producer (either as query string for GET or as form for PUT/POST).
- The encoding how to encode the property values of the link
- The method to call on the provided "href" value
This way, consumer would not need the URI template knowledge at all. Only the server would. And still there would be true value of describing these links in the schema, since this one provides the details of which link relation to lookup and which properties each of these links support (not to mention the documentation aspect of it).
--
This is not what I meant.For the following (pseudo)schema:{
"properties": {[...]}"links": [{"rel": "search","method":"POST","schema": {...},"encType":"application/json","targetSchema": {...}
}]}I meant receiving the following data:{[...]"links": [ {"rel"="search", "href"="/api/search"} ]}Now by looking up "search" LDO in schema, I would have all further details about how to interact with that related resource (doing POST, what properties to put and how to encode, etc.).
What about adding a unique-ID to LDOs so that you solve the issue of "matching" the LDO to the returned data representation returned link? This would solve the "rel" not unique issue?
items: | [ {
{
{ ]
| ||||||||||||||||||
next_page: | 2 | ||||||||||||||||||
@id: | http://localhost:5100/?per_page=3 | ||||||||||||||||||
page: | 1 | ||||||||||||||||||
per_page: | 3 |
links: | [ {
... {
|
OK, first: unfortunately "@" is not a valid character for variables in URI Templating. (to make things even more complicated, "{@}" was the equivalent of "{$}" for version 3 of the draft).
To let people use awkwardly-named variables in link templates, the standard defines some escaping rules for pre-processing. If you put the variable name in brackets, it should escape it for you:
{
"href": "{(@id)}",
"rel": "self"
}Use of such link will result in a request URI of something like "/search?term=whatever&resultsPerPage=10"
Secondly: the variables in the template come from the data - they are not editable. However, the "schema" property for links defines extra information to be supplied with the link. For a GET link, this information is appended as query parameters, for a POST link it will be included in the request body.
So for example, this is how you might describe a "search" link:
{
"href": "/search", <--- no variables here! Variables here come from the data
"rel": "search",
"method": "GET",
"schema": {
"type": "object",
"properties": {
"term": {"type": "string"},
"resultsPerPage": {"enum": [5, 10, 20], "default": 10}
},
"required": ["term"]
}
}
OK, first: unfortunately "@" is not a valid character for variables in URI Templating. (to make things even more complicated, "{@}" was the equivalent of "{$}" for version 3 of the draft).
Secondly: the variables in the template come from the data - they are not editable. However, the "schema" property for links defines extra information to be supplied with the link. For a GET link, this information is appended as query parameters, for a POST link it will be included in the request body.
...
Does that make sense?