Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Suggestion: Referencing specific array items in an ordered list with if-then-else #40

Open
CoderScribe opened this issue Aug 16, 2021 · 3 comments

Comments

@CoderScribe
Copy link

Hi guys,

A common scenario for us is to change our validation criteria in one array item, in an ordered array, depending on the value(s) of an array item that came before it. A generic example would be where array items represent columns or rows in spreadsheets.

Is this something that is possible? If So How? If not, could we please raise this as a suggestion.

Many thanks

@Relequestual
Copy link
Member

Hi @CoderScribe, unfortunatly this is not possible within the specification.

I'll migrate this issue to our vocabularies repo, which houses issues that could be potentially solved by a vocabulary.

Vocabularies are extensions to JSON Schema. You could write one yourself, but you'd also have to write the code to use any new keywords.

@Relequestual Relequestual transferred this issue from json-schema-org/json-schema-spec Aug 17, 2021
@jdesrosiers
Copy link
Member

It's interesting that this is a common scenario for you. In all my years writing JSON Schema and helping others solve their JSON Schema questions, I don't think I've ever come across that scenario. I wonder if there is some domain you are working in where there are other similar unusual constraints where it might be useful to construct a JSON Schema Vocabulary to address that domain.

Anyway, depending on exactly what your constraint is, there are some things you can do with JSON Schema. You can't do relative indexing, such as: if an array item's value is "foo", then the item before/after it must be a number greater than 3. But you can express something like: if item at index 2 is "foo", then the item at index 3 must be a number greater than 3. You are limited, however, to static assertions, meaning you can't make an assertion about the value of a field in relation to another field. For example, you can express: item at index 2 is greater than item at in index 3.

Here's an example of the kind of assertion you can make. This expresses the example given in the previous paragraph: if item at index 2 is "foo", then the item at index 3 must be a number greater than 3.

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",

  "type": "array",
  "prefixItems": [
    { "type": "boolean" },
    { "type": "string" },
    { "type": "string" },
    { "type": "number" }
  ],

  "if": {
    "type": "array",
    "prefixItems": [
      true,
      true,
      { "const": "foo" }
    ],
    "minItems": 3
  },
  "then": {
    "prefixItems": [
      true,
      true,
      true,
      { "exclusiveMinimum": 3 }
    ]
  }
}

If you are using a draft older than 2020-12, you can change prefixItems to items to get the same result. The general pattern is to express the general constraints of the schema at the top level, then the conditions below. We want the if to match on the third value and don't care about first two, so we can put true or {} stubs in those slots. Same concept applies to the then. This can result in a lot trues if you have a lot of items, but there's no way around it because there is no way to specify an index an array applies to. The minItems is also important because otherwise the if will match if the third item isn't present.

Let me know if that helps or if you have more questions.

@CoderScribe
Copy link
Author

CoderScribe commented Aug 26, 2021 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants