choices (v5 proposal to enhance enum) - sgpinkus/json-schema GitHub Wiki

THIS WIKI IS OBSOLETE. PLEASE SEE THE NEW JSON-SCHEMA-ORG/JSON-SCHEMA-SPEC REPOSITORY.


NOTE: This proposal has been migrated to https://github.com/json-schema-org/json-schema-spec/issues/57


Problem

the enum attribute for strings is really useful but has a severe limitation: it does not support providing a human readable label for raw values.

I tried workaround solutions but I prefer to stick to enum for its simplicity and for the fact that UI implementations (like JSON Editor) can very easily generate an HTML select with the allowed values.

Unfortunately though, enum cannot provide human readable values for decoration and documentation purposes (just like title and description properties included in the json-schema validation RFC), which makes it difficult to work with a long list of raw values that differ greatly from the corresponding human readable ones, for example, in a list of timezone settings for the entire globe, how can a programmer remember that "SAST-2" means "Africa/Mbabane" and "MST7MDT,M3.2.0,M11.1.0" means "America/Cambridge Bay".

The human readable value can be used for different purposes:

  • decoration
  • documentation
  • UI generation
  • validation error message generation

Solution proposed

Many popular frameworks like Django (python), Ruby on Rails (ruby) and Symfony (php) support specifying a list of choices, which are usually either a list of tuples or a dictionary (associative array), in which one element is the raw value while the other is the corresponding human readable label.

An example of a subset of choices for timezones:

[
    ["UTC", "Coordinated Universal Time"],
    ["GMT0", "Africa/Abidjan"],
    ["GMT0", "Africa/Accra"],
    ["EAT-3", "Africa/Addis Ababa"],
    ["WAT-1", "Africa/Bangui"]
]

Backward compatibility

Adding a "choices" (or an equivalent) attribute can be backward compatible with the current draft (v4): if both enum and choices would be present, choices would be used. if only enum is present implementations can still support it for backward compatibility.

Full backward compatible example:

{
  enum: ["UTC", "GMT0", "EAT-3"],
  choices: [
    ["UTC", "Coordinated Universal Time"],
    ["GMT0", "Africa/Abidjan"],
    ["EAT-3", "Africa/Addis Ababa"],
  ]
}

Advantages

Using a list of tuples (opposed as a list of objects) has the advantage of being a very simple, portable, and concise.

It's easier to maintain, faster to type and easier to read. Additional attributes can be allowed from the third element onwards if needed.

Another advantage is that this pattern is very well known in many MVC frameworks and it will result familiar to a lot of developers.

Downsides

The main downside is duplication of efforts when backward compatibility is needed: In an eventual transition from v4 to v5 both enum and choices should be supported in implementations. Popular schemas that aim to maximum compatibility also should use both.


Discussion

Named enumerations