6

In json schema, I can simply define a code list using "enum" with a list of code that is available, for example:

{
  "type": "object",
  "properties": {
    "group": {
      "type":"string",  
      "$ref": "#/definitions/Group"
    }
  },

  "definitions": {
    "Group": {
      "enum": ["A","B"]
    }
  }
}

And the following payload would be valid:

{
  "group": "B"
}

However, I try to provide the description in the schema to the user where "A" = "Group A", "B" = "Group B". Something like:

{
  "type": "object",
  "properties": {
    "group": {
      "type":"string",  
      "$ref": "#/definitions/Group"
    }
  },

  "definitions": {
    "Group": {
      "enum": [
        {"code":"A",
         "description": "Group A"
        },
        {"code":"B",
         "description": "Group B"
        }
      ]
    }
  }
}

But I don't want to change the structure of the payload (no "description" field needed) The description is more for documentation purposes that users can refer to. Is there a good practice that can be used here?

Thank you

James Yan
  • 61
  • 1
  • 2

2 Answers2

2

You can use anyOf with const instead of enum. Then you can use title or description for documentation.

{
  "anyOf": [
    {
      "const": "A",
      "title": "Group A"
    },
    {
      "const": "B",
      "title": "Group B"
    }
  ]
}
Jason Desrosiers
  • 22,479
  • 5
  • 47
  • 53
  • 2
    Either "anyOf" or "oneOf". I'd suggest "oneOf", since only one of these strings can match the value. But from a practical viewpoint, these are equivalent for this purpose. – jciloa Jan 13 '23 at 21:40
  • 2
    `anyOf` is the better choice in this case because it's more efficient. `oneOf` means one-and-only-one. If the value being validated is `"A"`, `anyOf` can stop evaluation after checking the first option. `oneOf` needs to evaluate every option to make sure that none of the other options also match. Since these options are all mutually exclusive, `oneOf` would be doing a bunch of unnecessary work. – Jason Desrosiers Jan 13 '23 at 22:19
  • @JasonDesrosiers sounds like premature optimisation to me. – Yogarine May 16 '23 at 20:34
  • @Yogarine I disagree. It's not premature nor an optimization. It's not premature because this is describing an enum. The values are by definition mutually exclusive. There's no value that could be added in the future that will change that. It's not an optimization because choosing a tool that does exactly what you need it to do and nothing else is not optimization. Schema authors should always use `anyOf` unless they specifically need an XOR rather than an OR. It's very rare that `oneOf` is the right choice. – Jason Desrosiers May 17 '23 at 00:42
  • @JasonDesrosiers > "The values are by definition mutually exclusive" < If they're mutually exclusive, then the definition needs to reflect that. "Mutually exclusive" means that only one value can exist at the same time. That's exactly what `oneOf` validates. You yourself proposed using `anyOf` "because it's more efficient." That combined with the fact it's a less correct validation implies sacrificing correctness for performance... an optimisation. It's premature because you're considering a minor optimisation over correctness without knowing if it is even measurable. – Yogarine May 19 '23 at 18:19
0

It depends on your tool-chain. For example the jsonschema2md allows to use meta:enum attribute for descriptions:

{
  "type": "object",
  "properties": {
    "group": {
      "type":"string",  
      "$ref": "#/definitions/Group"
    }
  },

  "definitions": {
    "Group": {
      "enum": ["A", "B"],
      "meta:enum": {
        "A": "Group A",
        "B": "Group B"
      }
    }
  }
}
eNca
  • 1,043
  • 11
  • 21