question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

`allOf` + `if/then/else` break when present at different levels.

See original GitHub issue

Prerequisites

Description

I tried to implement multiple if/then/else on nested objects.

While correctly working on nested objects, if I try to add a allOf on main object, this doesn’t work anymore.

Ex if you try to paste those schemas on the playground

  • OK

allOf in nested object

Playground Link

{
  "type": "object",
  "properties": {
    "animal": {
      "enum": [
        "Cat",
        "Fish"
      ]
    },
    "venue": {
      "type": "object",
      "title": "Location",
      "properties": {
        "space": {
          "enum": ["inside", "outside"] ,
          "default": "outside"
        }
      },
      "allOf": [
        {
          "if": {"properties": {"space": {"const": "inside"}}},
          "then": {"properties": {"room": {"type": "string", "enum": ["bedroom", "living room"]}}}
        },
                {
          "if": {"properties": {"space": {"const": "outside"}}},
          "then": {"properties": {"room": {"type": "string", "enum": ["garden", "terrace"]}}}
        }
      ]
    }
  }
}
  • Still OK

allOf in main object

Playground link

{
  "type": "object",
  "properties": {
    "animal": {
      "enum": [
        "Cat",
        "Fish"
      ]
    }
  },
  "allOf": [
    {
      "if": {
        "properties": {
          "animal": {
            "const": "Cat"
          }
        }
      },
      "then": {
        "properties": {
          "food": {
            "type": "string",
            "enum": [
              "meat",
              "grass",
              "fish"
            ]
          }
        },
        "required": [
          "food"
        ]
      }
    },
    {
      "if": {
        "properties": {
          "animal": {
            "const": "Fish"
          }
        }
      },
      "then": {
        "properties": {
          "food": {
            "type": "string",
            "enum": [
              "insect",
              "worms"
            ]
          },
          "water": {
            "type": "string",
            "enum": [
              "lake",
              "sea"
            ]
          }
        },
        "required": [
          "food",
          "water"
        ]
      }
    },
    {
      "required": [
        "animal"
      ]
    }
  ]
}
  • NOT OK

allOf in both main and nested object

Playground link

{
  "type": "object",
  "properties": {
    "animal": {
      "enum": [
        "Cat",
        "Fish"
      ]
    },
    "venue": {
      "type": "object",
      "title": "Location",
      "properties": {
        "space": {
          "enum": ["inside", "outside"] ,
          "default": "outside"
        }
      },
      "allOf": [
        {
          "if": {"properties": {"space": {"const": "inside"}}},
          "then": {"properties": {"room": {"type": "string", "enum": ["bedroom", "living room"]}}}
        },
                {
          "if": {"properties": {"space": {"const": "outside"}}},
          "then": {"properties": {"room": {"type": "string", "enum": ["garden", "terrace"]}}}
        }
      ]
    }
  },
  "allOf": [
    {
      "if": {
        "properties": {
          "animal": {
            "const": "Cat"
          }
        }
      },
      "then": {
        "properties": {
          "food": {
            "type": "string",
            "enum": [
              "meat",
              "grass",
              "fish"
            ]
          }
        },
        "required": [
          "food"
        ]
      }
    },
    {
      "if": {
        "properties": {
          "animal": {
            "const": "Fish"
          }
        }
      },
      "then": {
        "properties": {
          "food": {
            "type": "string",
            "enum": [
              "insect",
              "worms"
            ]
          },
          "water": {
            "type": "string",
            "enum": [
              "lake",
              "sea"
            ]
          }
        },
        "required": [
          "food",
          "water"
        ]
      }
    },
    {
      "required": [
        "animal"
      ]
    }
  ]
}

Food and water doesn’t appear anymore :

Screenshot 2022-03-08 at 21 47 51

Expected behavior

Conditional properties food and water should also appear when nested objects contains allOf

Version

    "@rjsf/bootstrap-4": "^3.2.1",
    "@rjsf/core": "^4.0.1",

Issue Analytics

  • State:open
  • Created 2 years ago
  • Comments:9 (1 by maintainers)

github_iconTop GitHub Comments

1reaction
phazebroekcommented, Sep 30, 2022

Using @rjsf/core 4.2.0, I’m seeing the same error reported for the following schema:

{
  "type": "object",
  "properties": {
    "liminar": {
      "type": "boolean",
      "title": "Há liminar?",
      "default": false,
      "enum": [
        true,
        false
      ]
    },
    "prazo": {
      "type": "string",
      "format": "date",
      "readOnly": true
    }
  },
  "allOf": [
    {
      "if": {
        "properties": {
          "liminar": {
            "const": true
          }
        }
      },
      "then": {
        "properties": {
          "prazo": {
            "readOnly": false
          }
        },
        "required": [
          "prazo"
        ]
      }
    }
  ]
}

However, if we not define “prazo” beforehand, it works:

{
  "type": "object",
  "properties": {
    "liminar": {
      "title": "Há liminar?",
      "type": "boolean",
      "enum": [
        true,
        false
      ]
    }
  },
  "allOf": [
    {
      "if": {
        "properties": {
          "liminar": {
            "const": true
          }
        }
      },
      "then": {
        "properties": {
          "prazo": {
            "type": "string",
            "format": "date",
            "readOnly": false
          }
        },
        "required": [
          "prazo"
        ]
      },
      "else": {
        "properties": {
          "prazo": {
            "type": "string",
            "format": "date",
            "readOnly": true
          }
        }
      }
    }
  ]
}

The observed behaviour makes sense to me and is not a bug but a feature imho. It will try to “merge” the readOnly property. But since it’s already defined, the value from “then” is ignored / overruled. As an alternative, you still can define the field upfront, but specify the readOnly true/false in either the “then” and “else” sections like so:

{
  "type": "object",
  "properties": {
    "liminar": {
      "type": "boolean",
      "title": "Há liminar?",
      "default": false,
      "enum": [
        true,
        false
      ]
    },
    "prazo": {
      "type": "string",
      "format": "date"
    }
  },
  "allOf": [
    {
      "if": {
        "properties": {
          "liminar": {
            "const": true
          }
        }
      },
      "then": {
        "properties": {
          "prazo": {
            "readOnly": false
          }
        },
        "required": [
          "prazo"
        ]
      },
      "else": {
        "properties": {
          "prazo": {
            "readOnly": true
          }
        }
      }
    }
  ]
}
1reaction
kfcaiocommented, Sep 12, 2022

Using @rjsf/core 4.2.0, I’m seeing the same error reported for the following schema:

{
  "type": "object",
  "properties": {
    "liminar": {
      "type": "boolean",
      "title": "Há liminar?",
      "default": false,
      "enum": [
        true,
        false
      ]
    },
    "prazo": {
      "type": "string",
      "format": "date",
      "readOnly": true
    }
  },
  "allOf": [
    {
      "if": {
        "properties": {
          "liminar": {
            "const": true
          }
        }
      },
      "then": {
        "properties": {
          "prazo": {
            "readOnly": false
          }
        },
        "required": [
          "prazo"
        ]
      }
    }
  ]
}

However, if we not define “prazo” beforehand, it works:

{
  "type": "object",
  "properties": {
    "liminar": {
      "title": "Há liminar?",
      "type": "boolean",
      "enum": [
        true,
        false
      ]
    }
  },
  "allOf": [
    {
      "if": {
        "properties": {
          "liminar": {
            "const": true
          }
        }
      },
      "then": {
        "properties": {
          "prazo": {
            "type": "string",
            "format": "date",
            "readOnly": false
          }
        },
        "required": [
          "prazo"
        ]
      },
      "else": {
        "properties": {
          "prazo": {
            "type": "string",
            "format": "date",
            "readOnly": true
          }
        }
      }
    }
  ]
}
Read more comments on GitHub >

github_iconTop Results From Across the Web

Validation: if/then/else · Issue #180 · json-schema-org ...
As I've written in some issue the schema with if/then/else: ... can either short-circuit "allOf", etc. or you can check all branches even...
Read more >
ifthenelse conditional & macro
What happens here is that TeX reads all of the argument to \ifthenelse with the currently active catcodes: those of a normal LaTeX...
Read more >
Ifelse - Amazon QuickSight
ifelse evaluates a set of if, then expression pairings, and returns the value of the then argument for the first if argument that...
Read more >
Using If...Then...Else statements (VBA)
The statement following the Else statement runs if the conditions in all of the If and ElseIf statements are False. VB Copy. Function...
Read more >
If..Then..Else | CueServer 2 Manual
Since no commands are present after the “Cue 1 Go”, an EndIf is not necessary. ... Then statements, all of the commands after...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found