-1

This MDN article here summarises quite well the technique of Content Negotiation on a REST API.

In essence, if we have a GET /student/:id endpoint, we might want to see different representations of that resource, (html, pdf, json, xml), and we can do this by attaching an Accept header to the resource.

They are all the same resource though - they're different representations of the same resource.

My question is - as a consumer of an API, it's very useful for me to have a JSON Schema that describes a resource.

Is it appropriate that one of the representations of a resource be that JSON schema? It would mean that GET /student/1 and GET /student/2 should always return the same result for example.

What's a tidier alternative?

1
  • Basically you request Accept: application/schema+json and you get a schema? Not a bad idea in practical terms.
    – user253751
    May 27, 2022 at 16:00

3 Answers 3

1

I think that this is a cool idea to the extent of it's intended purpose. That being said, I DO NOT think that it would be appropriate by any means to attach it to the GET /student/{id} endpoint. The reason being that it is generally not a good idea to try and condense multiple primary functions onto the same endpoint. Why not ConNeg (Content Negotiation)

"Tidier" Approach(s)

1. Just use GraphQL
This is by far my first choice when facing a situation where it would be beneficial for the requesting application to know some information about the objects which it is going to be querying. Primarily because it is a battle tested system, and has a large supporting ecosystem. If you are to go this route then you will want to look into the Introspection feature.
2. Extend Your Current REST Schema
I am assuming that the first approach is not an option for your specific scenario, but it would be remiss not to list it. The second option, would be to extend your current REST schema with a new endpoint.

This approach could be implemented in a few manners which would all be "tidy":

  1. The first would be to use GET /{Type} although this will only be doable if you are not going to be using the Type's root endpoint as a GET ALL function. (You should ONLY use this approach if NONE of your Types will be using the root as mentioned, the chosen approach should be CONSISTENT across the entire API)
  2. The second option, and in my opinion the best option, would be to simply define a new endpoint __schema which could then be appended to ANY existing endpoint without breaking already implemented code. Such as GET /{Type}/__schema The semantics would also make sense at any level of your API, for instance if you were to query the GET /__schema endpoint on your application root, then you could return the schema which describes all of the types in your application.
0

What's a tidier alternative?

Web Linking

Treat the description of the schema (which itself might have multiple representations) as a resource on its own. Create a link from the business document to its schema.

A link is triple, composed of a context (the current document) a target (the schema) and a relation type, which identifies the semantics of the link.

If there is a registered link relation that matches your needs, you should use that; otherwise, you can define your own extension relation type.

Of the registered link relations, describedby seems a likely candidate for what you want:

The relationship A 'describedby' B asserts that resource B provides a description of resource A. There are no constraints on the format or representation of either A or B, neither are there any further constraints on either resource.

This is the recommendation you will find in draft-bhutton-json-schema-00

It is RECOMMENDED that instances described by a schema provide a link to a downloadable JSON Schema using the link relation "describedby"...

This open issue might also be a good review, as the commentary goes deep into the different considerations involved.

0

What's a tidier alternative?

In the vast majority of causes this is just documentation for devs who have to implement the client, so there is no reason for it to be returned with the resource itself. By the time the client is interacting with a resource it should already know what it does and doesn't understand.

Think of it this way, nearly all websites will return a HTML 5 document, but it would be a bit silly if each webpage across the entire web could also returned the HTML 5 spec as well, and the browser isn't going to dynamically learn HTML 5 in time to parse the website either.

If you want to know how to build a client that understands HTML 5 you go to the specific resources that describe the HTML 5 spec (eg https://dev.w3.org/html5/spec-LC/)

So I tidier alternative would be to publish you any custom data formats you use some where anyone implementing a client that talks to your API can find, such as a 'Client implementation' doc or site.

2
  • 1
    There are a lot of use cases where you might use a json schema to dynamically drive behaviour. For example you might be creating forms using react-json-schema-form.
    – dwjohnston
    Jun 1, 2022 at 12:04
  • 1
    That isn't a use case I'm that familiar with, but principle remains the same. Whether it is a human dev reading a schema and implementing it or dynamic client doing it it still makes sense to seperate the resources since they are different things. Jun 1, 2022 at 12:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.