1

Context

In our project, we need to represent resources defined by the users. That is, every user can have different resources, with different fields, different validations, etc. So we have two different things to represent in our API:

  • Resource definition: this is just a really similar thing to a json schema, it contains the fields definitions of the resource and its limitations (like min and max value for numeric fields). For instance, this could be the resource definition for a Person:
{ "$id": "https://example.com/person.schema.json", "$schema": "https://json-schema.org/draft/2020-12/schema", "title": "Person", "type": "object", "properties": { "firstName": { "type": "string", "description": "The person's first name." }, "lastName": { "type": "string", "description": "The person's last name." }, "age": { "description": "Age in years which must be equal to or greater than zero.", "type": "integer", "minimum": 0 } } } 
  • Resource instance: this is just an instance of the specified resource. For instance, for the Person resource definition, we can have the following instances:
[ { "firstName": "Elena", "lastName": "Gomez", }, { "firstName": "Elena2", "lastName": "Gomez2", }, ] 

First opinion

So, it seems this kind of presents some conflicts with the Restful API approach. In particular, I think it has some problems with the Uniform Interface. When you get a resource, you should be able to handle the resource without any additional information. With this design, you need to make an additional request to first get the resource definition. Let's see this with an example:

Suppose you are our web client. And you are logged in as an user with the Person resource. To show a person in the UI, you first need to know the structure of the Person resource, that is, you to do the following request: GET /resource_definitions/person. And then, you need to request the person object: GET /resource/person/123.

Second opinion

Others seem to think that this is not a problem and that the design is still RESTful. Every time you ask for something to an API, you need to know the format previously, is not self-documented in the API, so it makes sense for this endpoint to behave the same as the others.

Question

So what do you think? Is the proposed solution compliance with the RESTful approach to API design?

2 Answers 2

2

The simple solution is to add a link:

{ "_links": { "describedby": { "href": "https://example.com/person.schema.json", "type": "application/schema+json" } }, "firstName": "Elena", "lastName": "Gomez" } 

You could also put this in a header. This is semantically equivalent:

Link: <https://example.com/person.schema.json>; rel="describedby" type="application/schema+json" 
Sign up to request clarification or add additional context in comments.

4 Comments

I like that solution, but I think the core problem of the question still remains: you need an additional request. Is true though that with your solution you at least know where to get the resource definition. Also, if we are not using schema+json, could you just set application/json as type?
@AntonioGamizDelgado You can as long as the JSON structure is documented. In your case the example.com/person.schema.json where you define the structure so simply referencing it is enough to meet the uniform interface constraint as long as the upper is HAL+JSON or you use the Link header.
@AntonioGamizDelgado application/schema+json is the correct type for this, so you should use that. Doing an additional request is fine.
@Evert Especially if it is HTTP2. :-)
1

It does not violate the uniform interface if there is no standard for this kind of stuff, but there is. RDF e.g. JSON-LD and schema.org vocab can handle most of these types. Even for REST there is an RDF vocab called Hydra, though the community is not that active nowadays.

As of the actual problem, I would look around, maybe RDF technologies or graph technologies are better for it, though I am not sure how much connection there is in your graph. If it is just a few types and instances, then I would probably stick to REST.

Ohh I see meanwhile, you used an actual JSON schema. Then that part is certainly uniform interface compatible. As of the instances you need to add something like type: "https://example.com/person.schema.json" and you are ok. Maybe a vendor specific JSON derived MIME type which describes what "type" means in this context if you want to be super precise or just use JSON-LD instead. https://www.w3.org/2019/wot/json-schema Or an alternative more common solution is using RDFS and XSD with JSON-LD instead of JSON Schema.

3 Comments

Uoh, I was totally unaware of all of those concepts. I will need some time to go through them. Just by the skimming through I have done, I can say I don't like how ugly that format seems, so I fear the consumers of the API will have a hard time getting used to use it.
@AntonioGamizDelgado If you mean JSON-LD, it better to read a lot about it before judging. You can have something almost identical with the upper JSON Schema plus a @context property if you define your own API specific vocab. But it is a really complex topic.
I agree, I still need to do a lot of studying about this.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.