Skip to content

✨ Proposal: Support $ref-to-enum in object required #1551

Open
@etinquis

Description

@etinquis

Describe the inspiration for your proposal

High-Level goal:
I want to be able to consolidate and re-use what are practically-speaking a static set of property names or object keys within a schema such that I am able to maintain the list in one place and reference them as either object property names or values, depending on context.

[My examples will assume I'm trying to define a schema for a localization data structure]

I start with a few enum schemas containing my keys.

{
    "$id": "/translation-slug.json",
    "title": "TranslationSlug",
    "enum": ["my_string_1", "my_string_2", /*...*/ ]
}
{
    "$id": "/locale.json",
    "title": "Locale",
    "enum": ["en", "fr", /*...*/ ]
}

I can reference this enum as values for properties on objects as so

{
    "$id": "/translation-assignment.json",
    "title": "TranslationAssignment",
    "type": "object",
    "properties": {
       "locale": { $ref: "/locale.json" },
       "slug": { $ref: "/translation-slug.json" },
       "translator": { $ref: '/translator.json' }
    },
   "required": ["locale", "slug", "translator"]
}
{
   "locale": "en",
   "slug": "my_string_2",
   "translator": "me"
}

I can reference this enum to define property names on objects as so

{
    "$id": "/translated-batch.json",
    "title": "TranslatedBatch",
    "type": "object",
    "propertyNames": {
       "$ref": "/locale.json"
    },
    "additionalProperties": {
       "type": "object",
       "propertyNames": {
          "$ref": "/translation-slug.json"
       },
       "additionalProperties": {
         "type": "string"
       }
    }
}
{
   "en": {
     "my_string_1": "..."
   },
   "de": {
     "my_string_2": "..."
   }
}

Now I want to define my 'source-of-truth' translated string file format schema, where I want validation to fail if any property is missing:

{
  "en": {
      "my_string_1": "...",
      "my_string_2": "...",
      "my_string_3": "..."
   },
   "fr": {
      /* my_string_1 is missing! */
      "my_string_2": "...",
      "my_string_3": "..."
    },
   /* de is missing! */
}

Describe the proposal

Possibilities:

An 'overload' on required directly allowing references to enum schemas

{
    "$id": "/translations.json",
    "title": "Translations",
    "type": "object",
    "propertyNames": {
       "$ref": "/locale.json"
    },
    "additionalProperties": {
       "type": "object",
       "propertyNames": {
          "$ref": "/translation-slug.json"
       },
       "additionalProperties": {
         "type": "string"
       },
       "required": { "$ref": "/translation-slug.json" }
    },
    "required": { "$ref": "/locales.json" }
}

A new required-adjacent property allowing references to enum schemas

{
    "$id": "/translations.json",
    "title": "Translations",
    "type": "object",
    "propertyNames": {
       "$ref": "/locale.json"
    },
    "additionalProperties": {
       "type": "object",
       "propertyNames": {
          "$ref": "/translation-slug.json"
       },
       "additionalProperties": {
         "type": "string"
       },
       "requiredPropertiesEnum": { "$ref": "/translation-slug.json" }
    },
    "requiredPropertiesEnum": { "$ref": "/locales.json" }
}

Some way to define propertyNames from an enum in a way that also makes them all required

{
    "$id": "/translations.json",
    "title": "Translations",
    "type": "object",
    "propertyNamesRequired": {
       "$ref": "/locale.json"
    },
    "additionalProperties": {
       "type": "object",
       "propertyNamesRequired": {
          "$ref": "/translation-slug.json"
       },
       "additionalProperties": {
         "type": "string"
       }
    }
}

Describe alternatives you've considered

The only way I understand there to be to implement this currently to duplicate and inline the values separately into 'required'.

{
    "$id": "/translations.json",
    "title": "Translations",
    "type": "object",
    "propertyNames": {
       "$ref": "/locale.json"
    },
    "additionalProperties": {
       "type": "object",
       "propertyNames": {
          "$ref": "/translation-slug.json"
       },
       "additionalProperties": {
         "type": "string"
       },
       "required": [ "my_string_1", "my_string_2", ... ]
    },
    "required": [ "en", "fr", ... ]
}

This imposes a potentially significant maintenance burden whereby changes to the enum must be duplicated in the subset of places where the full set should be required. Failure to propagate those changes also risks falsely validating schemas 'silently' or failing what should be valid schemas without some sort of linting procedure that is capable of identifying this pattern.

Additional context

https://github.com/orgs/json-schema-org/discussions/818 was my original Q&A discussion post looking for whether this was possible.

Metadata

Metadata

Assignees

No one assigned

    Labels

    proposalInitial discussion of a new idea. A project will be created once a proposal document is created.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions