sylbru
sylbru

Reputation: 1609

Make a property required depending on a query parameter with OpenAPI and JSON-Schema

I have a REST API that support for most calls a with query parameter, allowing the user to specify which additional fields they want to load along with the resource’s basic data.

I can describe the query parameter with OpenAPI, and I can describe the format of the response with JSON-Schema. But how can I describe the relation between the parameter and the response?

What I want to describe is:

I would like this stuff property to be defined as required. Is there a way of doing this?

(What makes this probably even more impossible is that the value of with can be a comma-separated list of properties, but at this point I’m not hoping)

Upvotes: 0

Views: 1996

Answers (2)

Jayantha
Jayantha

Reputation: 2349

JSON schema: query string required

 schema: {
  tags: ["sample"],
  summary: "Set query string values to required",
  querystring: {
    type: "object",
    properties: {
      name: {
        type: "string",
      },
      address: {
        type: "string",
      },
    },
    required: ["name"],
  },
},

Upvotes: 0

Jason Desrosiers
Jason Desrosiers

Reputation: 24489

You can't do anything in JSON Schema using out of context data. So, the only way to do what you want is to put the query data into your response.

{
  "id": 123,
  "query": {},
  ...
}
{
  "id": 123,
  "with": ["stuff"],
  ...
  "stuff": { ... }
}

With pure JSON Schema or OpenAPI 3.1, you can use if/then and contains to express the conditional requirement.

{
  "type": "object",
  "properties": {
    "id": { "type": "object" },
    "with": { "type": "array", "items": { "type": "string" } },
    ...
    "stuff": { ... }
  },
  "required": ["id"],

  "allOf": [
    {
      "if": {
        "properties": {
          "with": { "contains": { "const": "stuff" } }
        },
        "required": ["with"]
      },
      "then": { "required": ["stuff"] }
    },
    ... additional conditionals ...
  ]
}

However, assuming you are on OpenAPI 3.0, you don't have if, then, or contains. It's still possible, but it gets a bit ugly because you need to use a bunch of confusing boolean logic concepts instead.

{
  "type": "object",
  "properties": {
    "id": { "type": "object" },
    "with": { "type": "array", "items": { "type": "string" } },
    ...
    "stuff": { ... }
  },
  "required": ["id"],

  "allOf": [
    {
      "anyOf": [
        {
          "not": {
            "properties": {
              "with": {
                "not": {
                  "items": { "not": { "enum": ["stuff"] } }
                 }
              }
            },
            "required": ["with"]
          }
        },
        { "required": ["stuff"] }
      ]
    },
    ... additional conditionals ...
  ]
}

Upvotes: 2

Related Questions