-
-
Notifications
You must be signed in to change notification settings - Fork 312
Does anyone actually use JSON Hyper-schema #48
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
From my point of view, I'd be happy to reboot the whole hyper-schema approach while preserving some specific elements. In my past work, we picked bits and pieces from JSON Hyper-Schema to assemble into an alternate approach that got broad buy-in where Hyper-Schema as defined did not. That has a bit more to do with what Hyper-Schema should look like in v6, but it does indicate (for me, at least) that the v5 cleanup can be pretty aggressive since we should expect significant changes for v6 anyway. |
@awwright I use it for defining a link with rel of "options" to then pull in the options for a select. Totally agree that it doesn't seem to be the best spec of the bunch and more than happy to re-work if there are changes. But just wanted to submit a use case for consideration. |
I use Hyper-Schema for all of my JSON based REST APIs (although I haven't had the opportunity in while). In fact, I would have very little interest in JSON Schema if it weren't for JSON Hyper-Schema. As far as I have been able to find, it is the only standard capable of doing hypermedia APIs in JSON properly (1). In REST, resources should be self descriptive giving you everything you need to know about what it is and what you can do with it. On the web this takes the form of links and forms. Many JSON standards out there can describe links, but only JSON Hyper-Schema can do something like a form. If you are familiar with the Richardson Maturity Model (2), all the other options are designed for Level 2 REST APIs. JSON Hyper-Schema is the only Level 3 option around. I created a little library a while back that allows you to create fully functional CRUD APIs by writing only Hyper-Schemas (3). These APIs can be used without any out-of-band knowledge using Jsonary's (4) generic Hyper-Schema browser. This library allowed me to walk through the workflow while designing APIs. Nothing else is capable of that. This was a much more long winded response than I planned on, but my ultimate purpose is to say that I am strongly against changing the Hyper-Schema approach. There are certainly things that can be cleaned up, refactored, or extended, but I'll be keeping an eye on any Hyper-Schema proposals to ensure that the spirit of Hyper-Schema is not lost. I'm all for the kind of changes it sounds like @awwright is talking about, but I am concerned about what I think I'm hearing from @handrews. I look forward to reading your proposals. (1) JSON-LD has Hydra and XML has XHTML, but JSON has only JSON Hyper-Schema |
We use JSON Hyper-Schema extensively in both our platform API and client (really just JSON Schema in the back-end for validation purposes). I have worked on another enterprise API that was based on the Siren specification, but JSON Hyper-Schema is far superior due to its insane flexibility, its ability to keep things DRY and support for meta schemas ✨. I completely agree with @jdesrosiers that Hyper-Schema is the only JSON-based hypermedia API specification that is truly Restful. My favorite aspect is how it doesn't require you to modify your API responses, it's entirely non-invasive and complementary. I'm not sure what issues you are having resolving your refs, but we have found The only "limitation" our team has encountered (really just an initial mis-understanding) has to do with entity instances that are required/used for resolving URI Templates into absolute URLs - the issue is that some APIs want to use deeply nested resources that require multiple entities, like so:
The questions we ran into were "Do we use the same entity instance? Another? If it's from another, how do we specify where the instance should come from?" Our complications were mostly due to the fact that we designed our schemas to map nearly 1:1 to our API's domain model entities, such that each schema correlated to a single high-level entity (and I believe this is the general idea, but I'm sure there's other opinions on that). We still referenced other schemas with Because of this, it wasn't initially clear that support for working with multiple entity instances when resolving LDO (Link Description Object) URI templates is possible with JSON Pointer references - otherwise the URI template slugs correlate with the defacto entity instance provided (http://json-schema.org/latest/json-schema-hypermedia.html#anchor8). The question you still have to answer in your client, though, is what entity should be used when the reference is say Once our client-side API resolves the URI Template into a URL based on the provided entity instance, we then just construct an HTTP/REST resource caller that automatically follows whatever method is defined in the LDO Edit: couple typos |
@jdesrosiers Great feedback, thanks! As how REST has the code-on-demand constraint (which I take as including scripts and stylesheets), I sort of view JSON Schema as similar to a stylesheet, JSON Schema tells you how to render or how to work with the data you've been given. One of my outstanding concerns with JSON Hyper-schema is it has a "method" property combined with "href" and "rel". A link is supposed to describe relationships between resources, not necessarily listing things to do. Retrieving information about an associated resource is GET, HEAD, or OPTIONS, changing a resource is PUT or PATCH, executing some remote function is POST. Can you provide some more examples of how you'd like to approach linking? I'm re-reviewing the Richardson Maturity Model, which is so great for describing what RESTful really means. I'm also reviewing RESTful Web APIs by Leonard Richardson & Mike Amundsen (the legends of hypermedia protocols). |
@jdesrosiers while I would happily reboot hyper-schema, a more incremental approach based on adding rather than changing is entirely possible. Honestly, I've been saying provocative things about hyper-schema mostly to motivate people to actually speak up. "Resourceful" looks really interesting, I'll have to look into it more deeply. Part of my interests here have been around seeing if anyone has developed best practices for hyper-schema that mitigate the problems we found. If so, I am absolutely not dead-set on changing it. I agree that JSON Hyper-Schema is the only thing that comes close to RMM Level 3. It is actually what helped me sell RMM Level 3 at Riverbed, but ultimately the team found hyper-schema too confusing to accept. At a high-level there were three problems, ranging from annoyances to deal-breakers. I was going to wait and file proposed solutions (um... after I figured them out), but since we're seeing some life here, let's just look at the problems. Perhaps someone else figured out a way around these, or can explain what we missed along the way. This is, of course, my personal opinion and recollection several years down the road, and not the official opinion of my employer at the time (or current employer). Implicitly defined resourcesHyper-Schema implicitly defines resources by defining links to them. Every schema that has a self link is a resource (relatively explicit), and every link URI that is not otherwise accounted for in a self link is also a resource (it can be confusing to line these all up). This means there is no straightforward listing of resources anywhere obvious. Unless every resource is accessible from the root, which is not the case in many non-trivial APIs. It also means that with link URI templates defined all over the place, it is easy to produce conflicts, which also plays into the next problem. This is the problem that only some people considered a deal-breaker. I was not one of them, but there were very strong opinions about this. Our solution was to separate the declaration of resources and links from the schemas. Schemas could be defined inline within the resources, but usually were $ref'd in. I would like to sort out best practices for making the resources more clear, but am not at all attached to the separate enumeration approach. I can see "fixing" this just by implementing the documentation generator in a way that pulls the resources out and enumerates them clearly in the docs. Repetition in link definitionsThere's a lot of repetition in link definitions, or else functionality left out that should be doable in one step. Simply put, if I can do all the usual CRUD stuff on books and people, and a book has a list of authors, all of the links I define on authors are redundant. They're already defined for people. But I have to re-define them with a slightly different URI template of "/people/{authorId}" instead of "/people/{id}", and re-define the schema non-authoritatively in What makes more sense when both resources are described in the schema is is to be able to define a relationship between books and people with a This approach doesn't technically make anything impossible, but it was considered excessively burdensome. The only way we would have been able to use JSON Hyper-Schema would have been to write a pre-processor that duplicated all of the links out to the proper places. Our solution to this was just to add a "relation" field that referenced the other resource (it helped to have resources enumerated separately here, but is by no means required), and provided a map from the source schema's fields to the destination schema's self link URI template. This was done by the [edit- removed the bit about href duplication from Another benefit of this solution was that it removed the need for most I like this solution very much, but would be happy with anything that satisfied the same requirements of eliminating the duplication and more clearly showing resource-to-resource relations. Can't describe both URI parameters and a message bodyThis makes JSON Hyper-Schema unusable for me. There is only one Our solution is the one described in issue #52 (extended The extended |
@awwright : your comment here
captures my key concern in 500% less words :-) Basically, resources are not a first-class concept in JSON Hyper-Schema. They kinda just happen, and a lot of weirdness exists around that. |
@slurmulon I'm looking at "rel"... the current draft wants to add four values to the IANA registry and I'm not sure all those are necessary. As for nested resources, unfortunately I'm not really sure how to handle the more complex URI cases. Consider, though, if you're listing an absolute URI in a URI Template, then you're sandboxing yourself inside that namespace. It means if I want to store instances of resources on my server, I have to modify the schema so it points to my server instead of yours. So increasingly, I think the best design pattern is that JSON documents should provide pre-computed absolute URIs or URI references, and minimize computation. The only time I would use an absolute URI in a URI Template would be if it's globally assignable anyways, like "urn:uuid:{uuid}", "ni:///sha-256;{hash_sha_256}" and the like. The other alternative is we provide some way to let a script compute a value on a JSON instance, including provide a list of link relations. This is certainly within the scope of REST, but it seems excessive. |
@awwright : We set a base URI for all of our schemas and then if the template began with Anyway, this removed all need for absolute URIs for us except when going outside of the API entirely, in which case it was fine. We needed to be able to define URIs relative to the API base without having to repeat the API base (e.g. "/some/api/base/path" in "https://api.example.com/some/api/base/path") all over everything. |
@awwright Regarding nested resources and how they are currently handled, I stumbled across something like this (yes, with encoding):
I'm unable to find the resource for this, I ran into it months ago and it's very possible that it isn't officially supported (not seeing anything mentioned here: https://github.com/json-schema/json-schema/wiki/href or in the spec). Anyways, it's the closest thing I could find that would allow us to support multiple entity instances (our API team was annoyed with this fact, but I don't think it's a big deal at all). We had to write our own LDO I agree that you should minimize computation with your links, it will generally make everybody's life easier. I think though that it will still be necessary, even for common cases such as Even with globally unique identifiers, you still need to ask the question of "which instance do I use for the other entity/entities?" in the case of LDOs with more than one entity reference. With one entity it's trivial, because you can always just associate the schema/schema validator with whatever entity you want. But when there is a nested entity, it must either also be explicitly provided by the dev (increasing domain coupling, nipping away at a clean design) or implicitly provided by some state management system, and that (to me) is the hairy part. But again, I think this is primarily a concern of layers above JSON Hyper-Schema. Edit: clarity, grammar |
I've noticed this as well, what do you think can be done to help alleviate/fix this? What if you say that an LDO
Otherwise, if it's a single value, It seems this could help to eliminate redundancy in the LDOs as well since there's no need to duplicate links for additional actions that can be made on a resource. Perhaps the example I provided could be collapsed even further with URI Templates, such that |
@slurmulon We could have a field similar to HTTP "Allow" that specifies which methods the resource is capable of handling. So if "PUT" is missing, then it's a read-only resource; if POST exists, then it's an executable resource; etc. @handrews See how many of those concerns have issues filed against them? I should create a milestone for this maybe. |
@awwright yeah love it, that way |
Unlike jsonschema-core and jsonschema-validation, I'm at something of a loss for how to save jsonschema-hyperschema. My best idea right now is I'll rewrite major sections of the spec, and won't be afraid to break reverse compatibility with existing implementations. These are just Internet-Drafts, after all, and I think this is warranted because HTML, Atom, HTTP Link, HAL, etc, have much bigger adoption and are far more consistent, and have probably seen better adoption because of their consistency. These are the following features I'm looking to gently change or preserve, everything else I'll tear out unless someone says they'd like it:
During my survey, I found or came up with these features that I think would be useful:
I'll create issues for these enhancements. Please let me know all your opinions! |
@awwright Wow, I did not know that Hyper-Schema was in such a dire place - I have experience with HAL, JSON-LD, Siren, and more, and JSON Hyper-Schema is by far the most extensible and non-invasive hypermedia spec I have ever encountered. Its ability to represent and work with highly-complex data structures is simply unparalleled, and the fact that it establishes a unified validation language between layers of the stack is absolutely incredible (and generally long desired!) as it completely prevents any sort of code duplication or parallel business logic across layers. Its integration with things like API Blueprint allows you rapidly accelerate productivity with tools like Drakov (mock server) and Dredd (test your API Blueprint, and the JSON Schemas defined in it, against a real API). These are all amazingly helpful features that other specifications simply don't have, don't allow, or struggle with greatly. I'm happy to do whatever I can to help keep the spirit alive (documentation, technical/design discussions, whatever). I believe a lot of this stems from a lack of documentation / examples that give people their "Aha!" moment. It took our team a minute to realize the magic of Hyper-Schema, but once our team did it was a no-brainer as to how much it could help, and it did. As for the feature list you mentioned, I love the idea of a As for Regarding I really love the idea of "forProperties, forItems, forAdditionalProperties, forAdditionalItems (descend into an array or object, but links still describe the current JSON instance)" - this would allow semantic iteration through specific areas of an instance object, which is great! This wasn't mentioned, but I like the idea of adding |
@awwright @handrews I would love to join the organization if you're accepting members. I use JSON Hyper-Schema in many of my projects (including enterprise ones), so I am very passionate about the role that it can play in the Hypermedia world and have a lot of incentive to keep the ball rolling. Please feel free to email me at [email protected] if you'd like to discuss this further! |
@slurmulon I don't have any official position here myself, I'm just talkative and opinionated :-) |
@slurmulon Luckily I don't see the spirit of hyperschema changing at all, I think we're just realizing there's a small handful of things that don't mesh well with current hypermedia design best practices.
Regarding $ref in LDO, can you file a new issue that includes some examples and use cases? |
@slurmulon and @awwright : I'm extremely confused by both of these things:
Are these attempts to use parts of the instance data other than the immediate properties for resolving the URI template variables? Or for using instance data from within elements of a list or properties of an object within an instance? If so, those problems are solved very cleanly by the advanced templating proposed in in issue #52 which we used extensively throughout a set of APIs involving about 200 or so resources. I'm honestly baffled at the lack of reaction to that proposal, as it's the single most essential proposal outstanding for hyperschema for me (among other things, it is necessary to solve the failure to handle both URI parameters and message bodies, and (with relative JSON pointers) it handles URI parameters far more flexibly and elegantly than anything else I've seen proposed- no awful %37elf mess. |
@awwright yeah "spirit" probably wasn't the best word choice - I guess I meant "momentum" since the title of this issue is "Does anyone actually use JSON Hyper-Schema?" hehe
Cool, that makes sense. I was making a wrongful assumption of how the value would/could be used.
More than happy to file an issue that includes some examples and use cases. Stepping out for a few hours right now but will get to it later tonight/ |
@slurmulon You put |
@handrews regarding the work you did for #52 looks extremely useful and elegant - speaking for my own example, yes, it's an attempt to use parts of the instance data to resolve URI Templates (and instance data that potentially correlates to another schema, which raises the difficult question of "which entity instance should I use?"). I'm happy to help create examples, justifications, whatever, if you think that might help get things moving I would like to see how you are using |
I was hesitant to comment on this issue because I don't have the time to adequately keep up with the discussion. So, I'm sorry, I won't be able to answer all of the questions or comment on all of points made (at least not in a reasonable timeframe). For now, the following is how I think about Hyper-Schema in response to @awwright's inquires. As for specific difficulties with Hyper-Schema, @handrews, I'll try to address that at a later time if I can. When thinking about REST architectures, I find it useful to make analogies to it's reference implementation, the web. However, it is important to remember that the web doesn't define REST, REST describes the web (for the most part). So, the analogy is not always perfect. A JSON document is analogous to an HTML document. A Hyper-Schema can be linked in much the same way as a stylesheet, javascript, or image to completely describe the resource. This is where Hyper-Schema most deviates from the HTML analogy. It would be like if all the links and forms in your HTML were defined in a separate resource. It's different, but I've tentatively convinced myself that it doesn't violate any REST principles and it definitely has it's advantages. To make the analogy more clear, it helps to think of the analogy to HTML as the JSON document + the Hyper-Schema. The next part of the analogy is hyperlinks like the anchor tag LDOs are an analogy to an HTML One last analogy is Web 1.0 vs Web 2.0. Web 1.0 describes a web that is mostly static. It is mostly driven by hyperlinks and there are very few opportunities for users to interact or contribute content. Web 2.0 describes a web that is dynamic and makes heavy use of forms to interact with users. Other hypermedia solutions are capable of describing Web 1.0 style APIs were resources are largely read-only. Hyper-Schema allows a Web 2.0 style API that is naturally interactive. By naturally, I mean that there is no out-of-band information necessary to use it. That means a Hyper-Schema driven API needs no documentation to use it in the same way a website needs no documentation. Everything you need to know to use the website is included in each request. Ok, I lied, I do have one more analogy. One last thing, @handrews, I don't understand your position that Hyper-Schema is not resource-oriented. All interactions are done through interacting with a resource. The resource itself describes what you can do with it. What could possibly be more resource-oriented? |
@slurmulon : For the examples, I'll send you info offlist- anyone who also wants info just comment or or start a thread on the Google Group. If anything interesting comes out of offlist discussions I'll post a summary back here. I am a bit confused still about "instance data that potentially correlates to another schema". Do you mean the schema for a different resource, or do you mean a parent or child schema of the one defining the link? To give credit where credit is due, the extended templating proposal was originally from Geraint Luff. We built on that with the "relations between resources" concept I mentioned earlier, but it was mostly already proposed. |
@handrews thanks for adding me to the Google Group, sounds good. Regarding "instance data that potentially correlates to another schema", consider this URI template:
If we only had When there is more than one identifier slug, such as with
But if you want to keep your schemas and API resources relatively normalized (which I generally do, not sure if most people feel this way), nested identifiers introduce a problem. This is why the syntax I mentioned above, using the encoded JSON Pointers, answers this question at least partially, the question of what schema should this URI Template slug correlate to. It does not, however, answer the question of which entity instance to use - this needs to be answered by the developer for sure, but the question becomes much harder when there are two entities to juggle instead of one in the client. |
@Relequestual I include Hyper-Shema keyword in the response schemas, but not in the response instance data. That lets me use links from the response document, without the links appearing inline in the response. |
@Relequestual actually it's more accurate that I define a resource's representation, including its links, under So something like this, where I define a collection resource, an item resource, give them both "self" links and the appropriate side of the standard "collection" and "item" links, and use a custom link to connect the entry point to the collection: {
"definitions": {
"identifier": {
"description": "32-character hash identifier",
"type": "string",
"minLength": 32,
"maxLength": 32,
"pattern": "[0-9a-f]+"
},
"foo": {
"$id": "#foo-item",
"type": "object",
"properties": {
"id": {"$ref": "#/definitions/identifier"}
},
"links": [
{
"rel": "self",
"href": "/foos/items/{id}",
"hrefSchema": {
"type": "object",
"properties": {
"id": {"$ref": "#/definitions/identifier"}
}
},
"targetSchema": {"$ref": "#foo-item"}
},
{
"rel": "collection",
"href": "/foos",
"targetSchema": {"$ref": "#foo-collection"},
"schema": {"$ref": "#foo-item"}
}
]
},
"foos": {
"$id": "#foo-collection",
"type": "array",
"items": {
"allOf": [
{"$ref": "#foo-item"},
{
"links": [
{
"rel": "item",
"href": "/foos/elements/{id}",
"targetSchema": {"$ref": "#foo-item"}
}
]
}
]
},
"links": [
{
"rel": "self",
"href": "/foos",
"targetSchema": {"$ref": "#foo-collection"},
"schema": {"$ref": "#foo-item"}
}
]
}
},
"link": [
{
"rel": "tag:example.com,2017:foos",
"href": "/foos",
"targetSchema": {"$ref": "#foo-collection"}
}
]
} |
Thanks, that's what I though. I was pretty sure that was the case, but some of the discussion here confused me. |
I'm not sure I totally understand the phrasing you've used there, but I'll paraphrase what I understand when in conjunction with your example and you can tell me if I'm getting it or not. You include the collection and single link in both the collection and single definitions, so it's clear how to get from one to another. Cross referencing them in a sense. Right? My only query from that schema is what you're trying to imply by having...
Maybe this conversation should be taken sideways into email... Breaking my own rule of clogging up an issue... but it's a closed one so not so bad I guess. |
@Relequestual @jdesrosiers I realized I did part of the example wrong. The "item" link should be from each item within the collection, not from the top level of the collection. That should make a lot more sense :-) @Relequestual: On the item's self link, and each collection element's item link, "targetSchema" is the individual item resource. That's what you GET or PUT. Or PATCH, but that's a bit more complicated so I'm ignoring it for now. Let's get clear on the rest of it first. On the item's collection link, and the collection's self link, "targetSchema" is the collection. Again, you GET and PUT that. But "schema" is the item. An IANA "collection" link relation implies that a POST to the resource of an item representation will create a new item. While not mandated by the collection/item link relation RFC, this collection usage is basically the only design convention that's universally agreed-upon in all interpretations of "REST". An API should document that it does indeed support that, but this hyper-schema tells you everything you need to know to understand this. The collection's "self" link has the same "schema" for the same reason, although at the "self" link relation does not determine anything about how POST is used. You need to notice that the "schema" schema has a "collection" relation that points back to yourself. Or notice that your "item" links points to the same thing as the "schema" schema. This is where things get a bit dodgy, and we need to put in more work. It needs to be fairly easy to recognize this sort of thing, but right now it's not entirely clear how that should work. |
@handrews, it looks like we take somewhat different approaches. Your example looks like a service definition approach to me because you have everything defined in one big hyper-schema. What schema do you link to when someone requests a single foo? Do you duplicate #foo-item? Or, does it always refer back to the entry point schema somehow? Below is how I would refactor your example to align with my approach. Each resource has a hyper-schema that applies to it. You might notice that I took out all uses of
{
"link": [
{
"rel": "tag:example.com,2017:foos",
"href": "/foos"
}
]
}
{
"$id": "http://api.example.com/schemas/foo-collection",
"type": "array",
"items": { "$ref": "/schemas/foo-item" },
"links": [
{
"rel": "self",
"href": "/foos",
},
{
"rel": "create",
"href": "/foos",
"method": "post",
"schema": { "$ref": "/schemas/foo-item" }
}
]
}
{
"$id": "http://api.example.com/schemas/foo-item",
"type": "object",
"properties": {
"id": {
"allOf": [{ "$ref": "#/definitions/identifier" }],
"readOnly": true
},
"foo": { "type": "string" }
},
"required": ["foo"],
"definitions": {
"identifier": {
"description": "32-character hash identifier",
"type": "string",
"minLength": 32,
"maxLength": 32,
"pattern": "[0-9a-f]+"
}
},
"links": [
{
"rel": "self",
"href": "/foos/items/{id}"
},
{
"rel": "collection",
"href": "/foos"
}
]
} In case it wasn't clear, when I said "a resource is described by" I mean it has a Link header with rel describedby that can be dereferenced get a hyper-schema that can be applied to that representation (thus adding links to the response). |
See, this is my problem. Just two people having different interpretations of what's expected by default. If it's not "well done" or unclear, then why leave it abigious when the spec allows you to be unabigious? I'll happily share my JSON Schema files when our API goes "live" to show you how I've done this, but as of right now I cannot share them. |
@jdesrosiers There are a few things I just didn't convey well or did mistakenly:
I'll comment again in a bit about where I still see differences. I need to think through the points I want to make a bit more first. |
@Relequestual I want to separate two different sorts of concerns:
The first set of problems are not things that we can or should solve as part of JSON Hyper-Schema. An example relevant here is that IANA-registered link relations are often intentionally under-specified so that they can be used in a very broad set of circumstances. The most significant difference between my schemas and @jdesrosiers's is in the choice of link relation type and the positioning of the links. I'm making an argument about what sort of assumptions you can make based on the presence of the IANA-registered "collection" and "item" link relations, even though the RFC that defines those relations does not require those assumptions, and therefore does not guarantee that they will always be correct. But that has nothing to do with JSON Hyper-Schema. We could use XML and still find ourselves debating whether "collection" and "item" convey all of the necessary information. What might be relevant is a question of whether JSON Hyper-Schema (or XML, or whatever) has or should have a mechanism of disambiguating standard link relation usage. Or describing custom link relation usage. Which I think is where @jdesrosiers's Relation Description Object proposal is coming from. But that's not specific to the choice of "collection" and "item" alone vs using a "create" relation. Once you split the ambiguity up like this, it becomes clear that it's not a fundamental problem with JSON Hyper-Schema. Figuring out what assumptions can be made for a given link relation is independent of media type. Specifying assumptions is potentially part of the media type, but not specific to these link relations. And the differences in approach here come down to choice of an under-specified standard link relation vs a fully specified custom link relation (albeit a highly intuitive one). |
@Relequestual, I think the problem is that there are no tutorials out there showing how it is supposed to work. This is especially true of draft-05 which was a significant change. My approach has been shaped primarily by one principle: It has to work in the Jsonary browser. If I can't navigate the entire API just by following links and filling in forms, then I'm doing something wrong. Here is the example we have been discussing as a simple static site http://hyper-foo.s3-website-us-west-1.amazonaws.com/?url=example.json. None of the unsafe methods are supported, but those links are defined so you can see it work. Also, the schemas are modified a bit because it only supports draft-04. Jsonary was created by the creator of JSON Hyper-Schema, so I see it as the reference implementation for the standard (draft-04 at least). |
@handrews, thanks for the clarification. It sounds like we are on the same page (or at least very close) after all. |
@jdesrosiers yay! :-) As I alluded to in the last comment, I think our difference is mostly about choosing which link relations to use and where to put them, and about how much we can assume from the presence of a particular link relation. While that's somewhat orthogonal to JSON Hyper-Schema itself, let me go into a bit more detail because I think the "create" relation in this case in part motivated by a weakness in Hyper-Schema as it currently stands. In general, I avoid relations like "create" that are actions, because the relation type name should describe the nature of the relation between the resource, rather than directly specifying a thing you can do with the resource. The important part of this is in avoiding having to specify one LDO per operation on the same target resource. This is where I think Draft-04 went wrong with its use of For any link with an HTTP URI scheme (with or without the -S, also CoAP or anything else with an explicit mapping to HTTP), a link indicates that the following are possible:
PATCH is more complicated as it should be expressed in terms of a patch media type, e.g. We do not currently have an effective and well-designed way to express in Hyper-Schema how much of the above is actually supported, or if the resource behaves in any non-standard manners that violate these exceptions. A hit at the values of the This is why I do not think that Draft-04 or Jsonary are the right approaches. Both (along with nearly all documentation systems I have seen) are too operation focused. It's still leftover RPC. It should be resource-focused, and the possible operations are derived from the protocol indicated by the URI scheme. POST has no standard for describing its request format, so it is given explicitly. The only thing we are missing is a way to indicate design-time choices to disallow some methods/operations. Although... Per RFC 5988, a link relation MAY specify that it implies certain operations (mapping to HTTP methods in this case) are or are not available. This is where I get the notion of assuming that a "collection" relation with a Note that not supporting creation and returning a 405 Not Allowed is fine. That's not violating the pattern, that's just opting not to implement it (a read-only collection). But specifying So where does that leave us? Well, I hope you can see why I am treating "collection" that way and not writing an explicit "create" relation, even if you don't find it compelling enough to adopt yourself. But mostly I agree with you that we lack tutorials and realty-tested best practices. For that, we just need to keep working on making this specification real, implemented, and running. |
@handrews, I agree with almost all of what you say. Just two points where I disagree. First, I don't share your concerns about the "create" relation. It looks like you are defining an action, but it can also be interpreted as defining a relationship to a resource that can be used to create something. Also, to be clear, this is the "create" relation that was defined in draft-04, not just some random description. However, I agree that "collection" could be used as well in this case. It may even be better. I'll have ponder that one a little longer. But that brings me to the other point I disagree with: the idea that the "collection" link can be expressed as a single LDO. How {
"rel": "collection",
"href": "/foos",
},
{
"rel": "collection",
"href": "/foos",
"method": "post",
"schema": { "$ref": "/schemas/foo-item" }
} But, if you have {
"rel": "collection",
"href": "/foos",
"schema": { "$ref": "/schemas/foo-item" }
} there is no reason |
This gets back to In Draft 06, the form-encoded URL query string and any and all other portions of the URI are more flexibly and comprehensively specified by Crucially, So in Draft 06, there is never any reason to use I have argued and continue to argue that having a keyword called But the documentation/hinting of HTTP method usage and the specification of URL query parameters vs request bodies are completely orthogonal problems, no matter what the HTML history is. HTML forms were designed to abstract the submission mechanisms away from human users, and have never evolved beyond their original limitations due to the rise of JavaScript. Web apps that want to do something other than the behaviors allowed by HTML forms get around it with JavaScript. That doesn't make any sense for JSON Hyper-Schema. It should be fully functional on its own, without requiring workarounds through code-on-demand. Anyway, a Draft 06
The request format for PATCH is determined by This is how linking works in most, if not all, hypermedia systems.
There are other JSON-based things that start describing methods, but they (and, I argue, Draft 04 of JSON Hyper-Schema) are confused about the difference between hypermedia (ensures that links can be recognized with enough protocol and link relation type information to allow a client to know how they could be used) and API specifications (describes the exact HTTP usage allowed for each instance of a link) We need to figure out something about API specification functionality, because people want it. But it is not part of hypermedia, and we need to keep those concepts separate. This could be done through another JSON Schema vocabulary, or it could by done the way the validation and metadata keywords are handled in the JSON Schema Validation specification: each keyword is clearly designated to function as either a validation or a metadata keyword. No keyword conflates the two. I think that ensuring that we separate those concerns, whether by vocabulary or just be documenting them as having different purposes, we will avoid a great deal of the confusion that is currently present. And perhaps that will also help us figure out a way to support APIs that abuse HTTP semantics without impacting either proper HTTP usage or documentation. |
@jdesrosiers Also, I forgot "create" was in Draft 04 (it and "instances" were removed in Draft 05). "instances" is obviously redundant with "collection". "create"'s closest IANA-registered analogue "create-form", which is a better link name (relation, not action). I think the "create-form" target resource needs to be the form rather than the resource to which the form is submitted, so that type of link would probably point to the collection's schema, because its "self" link's |
It seems that we have different interpretations of how the The way I see it, the After some more thought about "create" vs "collection", I've decided that I very much prefer your pattern of using "collection". However, I can't get over the fact that it is undocumented behavior. It doesn't matter how intuitive or widely accepted the pattern is, we can't just assume a relation that was clearly and formally defined also has this other behavior. It would be nice if "collection" defined this behavior, but since it doesn't, the options are to create a new pair of "collection" / "item" -like relations, or use the existing relations and augment their behavior with something like "create". I don't think that "create-form", as defined, can really fill the role that "create" played. A resource that is related by "create-form" is supposed to be a resource that contains a form. That doesn't really help. If we have a creation link on the foo-collection schema, we could have a "create-form" link on the foo-item schema that points to the collection. That IMHO is a proper use of "create-form". That doesn't mean I don't like your interpretation. I like the idea, I just think it differs from the intended semantics of "create-form". Of course we could always create a new relation with those semantics if we wanted. Maybe something like "create-schema". |
Could you cite some motivation for this view in Draft 06? The JSON Schema specification is our specification. It means what we way it means. If there is something in Draft 06 that implies that However, I cannot find any such statements looking over Draft 06 right now.
This is exactly why I say that I see room for disagreement here. But this also comes up over and over with IANA-registered link relations. They are intentionally broadly defined, and will continue to be intentionally broadly defined. I don't know what the solution is (other than making up more "create"-ish relation types). RFC 5988 explicitly forbids treating combinations of relation types differently from relation types that are present separately, so "collection" + "create" should not be treated differently from "create" or "collection" individually. One option is to document the usage of underspecified link relation types in a given API, but it's not clear to me how that fits with generic clients. It's not truly generic if you have to read non-standardized documentation. This exact ambiguity is where I am struggling most with how to approach hypermedia. |
I responded to some of this in #276, so I won't repeat that here.
And it has no behavior with DELETE. The fact that the behavior of
Good point. I don't think that would be an issue for "create", but it would for the "create-schema" concept.
Agreed. In fact I've found very few of the IANA registered relations to be usable outside of the specific context they were designed for. Even "edit", which seems like it should be fairly generic, references constructs defined in Atom and therefore isn't reusable outside of Atom. Clearly something more is needed. RDO is the best way I've been able to come up with to address this problem. |
I don't think it is.
The semantics of PATCH define the request in terms of both the resource representation and the request media type, so there is an indirect relation between PATCH requests and Of course the representation of the target resource is irrelevant to a DELETE request, and with a POST request there is no guarantee of any relationship between the target resource representation and the request document. So But all of this is defined by RFC 7231 (HTTP Semantics) and RFC 5789 (PATCH). It has nothing to do with JSON Hyper-Schema at all.
I still find the RDO an interesting concept, I'm just not convinced that it belongs in the Hyper-Schema spec. I'm not 100% convinced it doesn't, either. Mostly I feel like I'm missing something about link relation types. Which is why I'm pestering mnot on mnot/I-D#211 :-) |
@jdesrosiers I just read through RFC 6573: "The Item and Collection Link Relations So I think once Draft 06 is out the door I'll file a new issue for JSON Hyper-Schema to reference RFC 6573 and specify the semantics of those link relations in the context of The general issue of overly broad link relations is still an issue, but it seems like this case seems easy enough to solve. This would unambiguously replace Draft 04's proposed "instances" and "create" link relations with existing IANA-registered link relations. |
After discussion elsewhere with @handrews and rereading this issue, the problem (for me at least) is the false assumption that I can use JSON Hyper Schema to document my non hypermedia compliant API. I think what we need is a preface on how to determine if using JSON Hyper Schema is "right for my API", and how to identify (or define, I don't know) whay a hypermedia API looks like. Maybe explain a few different situations. It looks like draft-4 allowed the abuse of JSH to document non hypermeida APIs. I'm still wrapping my head round what hypermeida IS and how it can be used. Given I gave a talk about JSON Schema and how to use it for a hypermedia API last week, and I'm still a bit confused about stuff, I think this should be our main address for draft-7. |
@Relequestual FWIW I think that we should also have keywords that are documentation-oriented. I don't think that static documentation and dynamic hypermedia are incompatible, they're just different things that need different support. For instance, #73 is a way to support static documentation, but it did not get momentum for Draft 06 (and see also mnot/I-D#211 for more discussion related to the topic of HTTP hints). |
@Relequestual, I don't think it's right to think about Hyper-Schema as documentation. I often refer to Hypermedia APIs as self documenting, but it's more about reducing the number of things that need documenting. It's kinda like if you referred to the method signatures in your classes as documentation. In a way they are, but they are also parseable, executable, and an integral part of the system. |
@Relequestual @jdesrosiers I'm part of the way through a big comparison of hypermedia vs API description which I'll put on the wiki. Or maybe our web site through the other repo. I just got distracted replying to #280 so it will have to wait until tomorrow :-) |
Great thanks @handrews this will be super useful. I think as a first pass it should go on the wiki with a view to probably migrate it to the website once us non hypermedia understanding luddites feel the comparison and explaianition is sufficent to make sense =] |
@Relequestual you might find my schemas useful...I'm currently adding/updating them daily... Also see for examples of objects which are considered valid the schemas |
@handrews will you post an update here when done? I've always felt I didn't really understand the point of the hypermedia spec correctly coming from a different starting perspective. |
There's a lot of broken features defined in JSON Hyper-Schema, I want to ask implementors how much I can be allowed to "break" (i.e. make compliant with normative references).
Mostly things like quirks about how it defines URI templates, uses "rel", and uses "method".
Anyone?
The text was updated successfully, but these errors were encountered: