Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Weird Json Schema oneOf behavior in RJSF #4449

Open
4 tasks done
msharikhmarex opened this issue Jan 14, 2025 · 7 comments
Open
4 tasks done

Weird Json Schema oneOf behavior in RJSF #4449

msharikhmarex opened this issue Jan 14, 2025 · 7 comments
Labels
bug needs triage Initial label given, to be assigned correct labels and assigned

Comments

@msharikhmarex
Copy link

msharikhmarex commented Jan 14, 2025

Prerequisites

What theme are you using?

material-ui

Version

5.x

Current Behavior

I have the following schema which is rendered using react-jsonschema-forms framework. Link to playground here

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "definitions": {
    "XXXType": {
      "title": "XXXX",
      "type": "object",
      "properties": {
        "sourceType": {
          "type": "string",
          "enum": [
            "Xxxxx"
          ],
          "default": "Xxxxx"
        },
        "folioInstrumentFilter": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "folios": {
          "type": "array",
          "items": {
            "type": "integer"
          }
        },
        "xxxxxTradeIds": {
          "type": "array",
          "items": {
            "type": "integer"
          }
        }
      },
      "additionalProperties": false,
      "required": [
        "sourceType"
      ]
    },
    "YYYYType": {
      "title": "YYYY",
      "type": "object",
      "properties": {
        "instrumentTypes": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "minItems": 1
        },
        "books": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "tradeLegIds": {
          "type": "array",
          "items": {
            "type": "integer"
          }
        }
      },
      "required": [
        "instrumentTypes"
      ],
      "additionalProperties": false
    }
  },
  "properties": {
    "name": {
      "type": "string",
      "minLength": 1,
      "maxLength": 50
    },
    "portfolio": {
      "type": "object",
      "oneOf": [
        {
          "properties": {
            "name": {
              "type": "string",
              "enum": [
                "Name 1",
                "Name 2",
                "Name 3",
                "Name 4"
              ]
            }
          },
          "required": [
            "name"
          ]
        },
        {
          "type": "object",
          "properties": {
            "custom": {
              "oneOf": [
                {
                  "$ref": "#/definitions/XXXType"
                },
                {
                  "$ref": "#/definitions/YYYYType"
                }
              ]
            }
          },
          "required": [
            "custom"
          ]
        }
      ]
    }
  },
  "required": [
    "portfolio",
    "name"
  ],
  "additionalProperties": false
}

Change the DropDown in the form (as shown in the image between XXXX and YYYY

The form seems to fail validation in rjsf especially when I switch the inner oneOf between the XxxxxType and YyyyyType definition. It always complains that it doesn't match between one of the two schemas and must have required property 'name'. I have tried different permutations of RJSF options and nothing seems to work.

Also tried discriminating using "if" that that didn't work. I have spent a lot of time trying to figure this out and I can't figure out the issue. Your help is much appreciated. Note that moving the inner oneOf to top level (removing the nesting) makes it work (see link in "expected behaviour").

Expected Behavior

I have tried moving the inner oneOf at the top level see playground and it works as expected.

Expecting the input to stay valid when switching between the inner oneOf definitions.

Steps To Reproduce

Go to playground... select "XXXXX" for second dropdown (UI is valid). Change the drop down to "YYYY" you will get errors
image

I have attached an animated GIF to show how to reproduce.

Note that

  • Selecting XXXX after selecting Option 1 creates correct Json and is valid.
  • Switching to YYYY causes validation error (schema selection for oneOf).
  • Switching back to XXXX completely removes the element Json and fail validation.

Image

Environment

- OS: Windows 10
- Node: 20.18.1
- npm:10.8.2

Anything else?

No response

@msharikhmarex msharikhmarex added bug needs triage Initial label given, to be assigned correct labels and assigned labels Jan 14, 2025
@msharikhmarex msharikhmarex changed the title <title>Weird Json Schema oneOf behavior in RJSF Weird Json Schema oneOf behavior in RJSF Jan 14, 2025
@JinYuSha0
Copy link
Contributor

I think a property similar to the useForm mode should be implemented to better solve this problem. after Live validation is turned on, the actual validation behavior is “onMount”

@msharikhmarex
Copy link
Author

msharikhmarex commented Jan 20, 2025

Hi @JinYuSha0, how is useForm would fix this? do you know what is the underlying cause? Is there a workaround? I have also added an animated GIF that shows the actual bug.

@joesolly
Copy link

I took a look through this and I think the validation side is working as expected. When you switch to custom YYYY, you don't have a default value for the first item in the array, so you are not passing validation for the oneOf. The list of errors that are displayed is showing all of the oneOf possibilities and how you are failing all of them. I get around this by only displaying inline errors and not displaying form errors.

There does appear to be a bug with the defaults for the inner oneOf. When you switch from YYYY back to XXXX the default fields do not repopulate. I'm not sure why that would happen, but perhaps that would be a good first step to look into.

@msharikhmarex
Copy link
Author

msharikhmarex commented Jan 23, 2025

I took a look through this and I think the validation side is working as expected. When you switch to custom YYYY, you don't have a default value for the first item in the array, so you are not passing validation for the oneOf. The list of errors that are displayed is showing all of the oneOf possibilities and how you are failing all of them. I get around this by only displaying inline errors and not displaying form errors.

There does appear to be a bug with the defaults for the inner oneOf. When you switch from YYYY back to XXXX the default fields do not repopulate. I'm not sure why that would happen, but perhaps that would be a good first step to look into.

yes, I think you are correct, problem is that switching the inner oneOf causes an incomplet/empty values which causes the validation to fail. It is causing us lots of problems, do you think this is related to the structure of the schema?

@joesolly
Copy link

I took a look through this and I think the validation side is working as expected. When you switch to custom YYYY, you don't have a default value for the first item in the array, so you are not passing validation for the oneOf. The list of errors that are displayed is showing all of the oneOf possibilities and how you are failing all of them. I get around this by only displaying inline errors and not displaying form errors.
There does appear to be a bug with the defaults for the inner oneOf. When you switch from YYYY back to XXXX the default fields do not repopulate. I'm not sure why that would happen, but perhaps that would be a good first step to look into.

yes, I think you are correct, problem is that switching the inner oneOf causes an incomplet/empty values which causes the validation to fail. It is causing us lots of problems, do you think this is related to the structure of the schema?

I think I found a solution, because I do the same thing. If you add


        "sourceType": {
          "type": "string",
          "enum": [
            "Yxxxx"
          ],
          "default": "Yxxxx"
        },

To the YYYY definition, everything works. You could hide sourceType in the ui schema because you don't need it

@joesolly
Copy link

Well, it worked for me briefly, then it stopped working again. I'll keep chewing on it.

@joesolly
Copy link

Getting rid of liveOmit seems to help, although there are still some issues. I agree that this does seem to have something to do with nested oneOf values

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug needs triage Initial label given, to be assigned correct labels and assigned
Projects
None yet
Development

No branches or pull requests

3 participants