Skip to content

"allOf" Support for the custom JSON schema keywords merging  #3258

@Dzuming

Description

@Dzuming

Prerequisites

What theme are you using?

core

Is your feature request related to a problem? Please describe.

In a JSON schema, there is a possibility to use if else then. I want to define a JSON schema with a custom keyword

...
        "properties": {
          "hasDescription": {
            "type": "boolean"

          },
          "description": {
            "type": "string",
            "customProperty": {
              "isImportant": false
            }
          },
        }
...

"allOf": [
          {
            "if": {
              "properties": {
                "hasDescription": {
                  "const": true
                }
              }
            },
            "then": {
              "properties": {
                "description": {
                  "customProperty": {
                    "isImportant": true
                  }
                }
              }
            },
            "else": {}
          }
        ]

If all of the conditions are met in the form, there is a warning in the console, and values are not merged:

could not merge subschemas in allOf:
Error: No resolver found for key customProperty. You can provide a resolver for this keyword in the options, or provide a default resolver

Describe the solution you'd like

RJSF library uses json schema merge all library under the hood to merge subschemas. There is an option to add custom resolvers via options property .

Now, packages/utils/src/schema/retrieveSchema.ts code where merging happens looks like

 if (ALL_OF_KEY in schema) {
    try {
      resolvedSchema = mergeAllOf({
        ...resolvedSchema,
        allOf: resolvedSchema.allOf,
      }) as S;
    } catch (e) {
      console.warn("could not merge subschemas in allOf:\n" + e);
      const { allOf, ...resolvedSchemaWithoutAllOf } = resolvedSchema;
      return resolvedSchemaWithoutAllOf as S;
    }
  }

The idea is to be able to provide custom mergeAllOf resolvers

resolvedSchema = mergeAllOf({
        ...resolvedSchema,
        allOf: resolvedSchema.allOf,
      }, 
      {
          resolvers: customResolvers
) as S;

So the end result will be like

resolvedSchema = mergeAllOf({
        ...resolvedSchema,
        allOf: resolvedSchema.allOf,
      }, 
      {
          resolvers: {
            customProperty: function (values, path, mergeSchemas, options) {
              return { ...values[0], ...values[1] };
            },
          },
        }
) as S;

Describe alternatives you've considered

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions