Skip to content
This repository has been archived by the owner on Dec 5, 2019. It is now read-only.

Variables in schemas? #122

Open
maxlinc opened this issue Jun 6, 2014 · 0 comments
Open

Variables in schemas? #122

maxlinc opened this issue Jun 6, 2014 · 0 comments

Comments

@maxlinc
Copy link
Collaborator

maxlinc commented Jun 6, 2014

I had a thought... so I captured it. It's not something I plan to implement any time soon, but an idea I wanted to record for future discussion.

I remember talking with @JesusMercado or @marcosccm about templating, and how I only planned it for the "default" values in json-schema. For example

{
  "server_type": {
    "type": "string",
    "required": true,
    "default": "<%= %w(osx windows linux).sample) %>",
  }
}

I thought of some other scenarios where you might want variables in the schema. I'm not sure this is a completely necessary feature, or even the best way to support this - but it's got me thinking about the challenges and advantages.

Pagination limits

It's pretty common to have a "limit" or similar request parameter that defines the maximum expected size for a hash or array in the response.

So given a request:

GET /api/things?limit=5 HTTP/1.1

We might want a contract that has a response schema like:

{
  "things": {
    "type": "array",
    "required": true,
    "maxItems": <%= params['limit'] %>
  }
}

That way the actual use of the limit is expressed in the contract, and Pacto dynamically adjusts expectations as you send 1, 2, 5 or 100.

Searching

Another possible use is with searching. Suppose you send:

GET /api/things?q=max HTTP/1.1

You might want a schema like:

{
  "things": {
    "type": "array",
    "required": true,
    "items" {
      "type": "object",
      "properties": {
        "name": {
          "type": "string",
          "pattern": "<%= params['q'] %>"
        }
      }
    }
  }
}

Content negotiation

Or, there's possible examples with common request headers. You can probably do some powerful stuff with this, but it gets tricky pretty quick:

GET /api/things HTTP/1.1
Accept-Language: pt-Br
Accept-Language: en-US
{
  "$schema": "http://json-schema.org/draft-03/schema#",
  "type": "object",
  "properties": {
    "essays": {
      "type": "array",
      "required": true,
      "items": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "language": {
            "type": "string",
            "required": true,
            "enum": <%= headers['Accept-Language'] %>
          }
        }
      }
    }
  }
}

Summary

The tricky part here is that the Contract won't even load, because it can't parse the templates. It works okay when the template is inside quotes, but that doesn't work for json-schema keywords that expect a non-string value (e.g. integer for maxItems). Not only is it invalid json-schema, but it's not even valid JSON until we can process the template, which isn't really possible until we process an HTTP interaction.

I don't think we should support any of these scenarios right now, but:

  • It should be possible to write custom validation rules in Ruby that achieve similar results
  • If these scenarios are common enough, we might want to look into how we could parse the schemas above, or other ways to define similar behavior in the schemas.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

1 participant