react-jsonschema-form icon indicating copy to clipboard operation
react-jsonschema-form copied to clipboard

Issue with oneOf Validation in rjsf

Open dmistry1 opened this issue 1 year ago • 5 comments

Prerequisites

What theme are you using?

validator-ajv8

What is your question?

I'm working with a schema that uses the oneOf keyword to define two options, each with its own set of required fields. However, I'm encountering an issue where, after selecting one option and entering values, the validator incorrectly prompts for required fields from the other option.

Here’s a simplified example of my schema:

{
  "oneOf": [
    {
      "type": "object",
      "properties": {
        "optionAField1": { "type": "string" },
        "optionAField2": { "type": "number" }
      },
      "required": ["optionAField1"]
    },
    {
      "type": "object",
      "properties": {
        "optionBField1": { "type": "string" },
        "optionBField2": { "type": "number" }
      },
      "required": ["optionBField1"]
    }
  ]
}

When I select the first option and fill in optionAField1, I receive a validation error indicating that optionBField1 is required, even though it should not be necessary for the chosen option.

Is this a known issue with rjsf, or am I missing something in my schema configuration? How can I resolve this issue?

dmistry1 avatar Jul 19 '24 17:07 dmistry1

@dmistry1 can you double-check your schema & reproduction steps? I am trying to use your schema in the Playground here, and I can submit the data without errors

nickgros avatar Jul 19 '24 19:07 nickgros

@nickgros Taking the playground that you provided as an example, say a user fills out optionAField2 field which is not required and we call validate. In the screenshot that I have attached, we can see that we get an error must have required property 'optionBField1' even though we selected Option 1. image

dmistry1 avatar Jul 22 '24 13:07 dmistry1

With your schema, Ajv has no idea whether you picked 'Option 1' or 'Option 2'. That's entirely a UI construct. If you want Ajv to 'know' about the chosen option, you need to encode that choice into the schema. To do that you have a few options.

If/then/else

You could use "if"/"then"/"else" conditions in your schema so only certain subschemas are validated when the choice matches a certain value. See this example. Basically, your optionA subschema is only loaded when the formData option matches the chosen value.

Discriminator

We have some basic support for the OpenAPI discriminator keyword. Unfortunately we don't have many docs that describe how to use this, and actual Ajv support is a bit spotty. @heath-freenome and I had some luck transcribing your schema into the following example, and modifying the Ajv instance to enable discriminator support. We don't have a way to test this in the playground, so if you want to try this you will have to test it on your machine or in something like CodeSandbox.

{
  "type": "object",
  "definitions": {
    "OptionA": {
      "type": "object",
      "properties": {
        "option": {
          "type": "string",
          "default": "optionA",
          "enum": [
            "optionA"
          ]
        },
        "optionAField1": {
          "type": "string"
        },
        "optionAField2": {
          "type": "number"
        }
      },
      "required": [
        "optionAField1"
      ]
    },
    "OptionB": {
      "type": "object",
      "properties": {
        "option": {
          "type": "string",
          "default": "optionB",
          "enum": [
            "optionB"
          ]
        },
        "optionBField1": {
          "type": "string"
        },
        "optionBField2": {
          "type": "number"
        }
      },
      "required": [
        "optionAField1"
      ]
    }
  },
  "discriminator": {
    "propertyName": "option"
  },
  "oneOf": [
    {
      "$ref": "#/definitions/OptionA"
    },
    {
      "$ref": "#/definitions/OptionB"
    }
  ],
  "required": [
    "option"
  ]
}

nickgros avatar Jul 26 '24 20:07 nickgros

@heath-freenome added an option to the playground to test validation with an Ajv instance where the discriminator option is true.

@dmistry1 here's a playground example of the discriminator suggestion. Change the "Validator" option to "AJV 8 (discriminator)"

nickgros avatar Jul 29 '24 14:07 nickgros

@nickgros thank you so much for this information.

dmistry1 avatar Aug 06 '24 13:08 dmistry1

This issue has been automatically marked as possibly close because it has not had recent activity. It will be closed if no further activity occurs. Please leave a comment if this is still an issue for you. Thank you.

stale[bot] avatar Nov 06 '25 22:11 stale[bot]