Show fields conditional on other field value


#1

Hi!

I’m constructing a rather complex REST API where the response body can have different fields depending on a value in that same body.

I.e. two examples of responses from the same endpoint:

{
“fieldType”: “creditcard”,
“creditType”: “revolving”,
“creditLimit”: “15000”
}

{
“fieldType”: “mortgage”,
“creditType”: “fixed”,
“sanctionedAmount”: “850000”
}

As you can see in the example above, depending on “creditType” there will be different fields in the body.
Is it possible to document this with RAML?


#2

That might be difficult to model since semantics in data modelling are usually quite restricted. That does not necessarily mean you can’t inform your consumer on what they will need to expect by simply adding more text description.

BUT

Any client, or API consumer, will have its problem when you send different responses depending on some value. Maybe think about how to structure your API differently to avoid the client to parse the fieldType value before it can understand the rest.


#3

Hello, Loek.

You can use for this json-schema with oneOf. Example:

{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "object",
  "oneOf": [
    { "$ref": "#/definitions/fixedCreditType" },
    { "$ref": "#/definitions/revolvingCreditType" }
  ],
  "definitions": {
    "fixedCreditType": {
      "type": "object",
      "properties": {
        "fieldType": {"type": "string"},
        "creditType": {"type": {"enum": [ "fixed"]}},
        "creditLimit": {"type": "number"}
      },
      "required": ["fieldType", "creditType", "creditLimit"],
      "additionalProperties": false
    },
    "revolvingCreditType": {
      "type": "object",
      "properties": {
        "fieldType": {"type": "string"},
        "creditType": {"type": {"enum": [ "revolving"]}},
        "sanctionedAmount": {"type": "number"}
      },
      "required": ["fieldType", "creditType", "creditLimit"],
      "additionalProperties": false
    }
  }
}

Are you okey with this solution?


#4

So one thing you could do, which is not done often but is certainly possible, is to provide different media types for the different structures. I would argue though that while each response media type can alter the structure a bit, the resource should return data regardless of mediatype that are related to the resource. For example, you wouldnt want to return a Cat structure for a resource like /dogs.

What do I mean by media type? You can have the client pass in the accept header of what media types it accepts, if not all json. So, your resource could then return application/vnd.resolving+json for resolving credit and maybe application/vnd.fixed+json for fixed credit. In this way, you can define individual json schema structures for each response type, while maintaining that they are related to the resource (eg. credit types). The consume can then specify one, both, or any json via the Accept header and your service can look at the Accept header and return the appropriate type, or if necessary a 4xx response.

The thing is, I seldom see APIs using these custom mediatypes, but I believe this is one way, probably the only way you would want to return slightly different structures from the same resource.

I would say, do NOT force a consumer to have to parse a field of the response to figure out how to further parse the rest of the response. Use a mediatype, or separate the structures under different resources, OR use the same structure with different values, e.g. creditType is revolving or fixed regardless of fieldType value.