skip to Main Content

Hi I am pretty sure I am doing something wrong with my json schema, my usecase is that I add some elements to a table using documents and in this case the elements are added through name, value key pair. Now if the value of name is ‘name’ then it’s value pair should follow a regex validation, except for 1 particular scenario if the tableName where these are being added is header, in that case it should not follow this regex pattern.

my schema is ->

{
    "properties": {
        "elements": {
            "type": "array",
            "items": {
                "$ref": "#arrayElement"
            },
            "minItems": 1
        }
    },
"definitions": {
        "arrayElement": {
            "$id": "#arrayElement",
            "type": "object",
            "required": ["tableName"],
            "properties": {
                "tableName": {
                    "type": "string"
                },
                "elms": {
                    "type": "array",
                    "items": {
                        "type": "object",
                        "required": ["name", "value"],
                        "properties": {
                            "name": {
                                "type": "string"
                            },
                            "value": {
                                "anyOf": [
                                    {
                                        "type": "string"
                                    },
                                    {
                                        "type": "number"
                                    },
                                    {
                                        "type": "boolean"
                                    }
                                ]
                            }
                        }
                    },
                    "minItems": 0
                },
                "ele2": {
                    "type": "object",
                    "$ref": "#objectElement"
                },
                "ele3": {
                    "type": "array",
                    "items": {
                        "$ref": "#arrayElement"
                    },
                    "minItems": 0
                }
            },
            "allOf": [
                {
                    "if": {
                        "properties": {
                            "elms": {
                                "items": {
                                    "properties": {
                                        "name": {
                                            "const": "name"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "then": {
                        "allOf": [
                            {
                                "if": {
                                    "properties": {
                                        "tableName": {
                                            "const": "header"
                                        }
                                    }
                                },
                                "then": {
                                    "properties": {
                                        "elms": {
                                            "items": {
                                                "properties": {
                                                    "value": {
                                                        "type": "string"
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "else": {
                                    "properties": {
                                        "elms": {
                                            "items": {
                                                "properties": {
                                                    "value": {
                                                        "type": "string",
                                                        "pattern": "^[A-Za-z][A-Za-z0-9_.#/-]*$"
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        ]
                    },
                    "else": {
                        "properties": {
                            "elms": {
                                "items": {
                                    "properties": {
                                        "value": {
                                            "anyOf": [
                                                {
                                                    "type": "string"
                                                },
                                                {
                                                    "type": "number"
                                                },
                                                {
                                                    "type": "boolean"
                                                }
                                            ]
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            ]
        }
    }
}

Now this payload is passing through which should fail due to regex validation on name

"elements": [
        {
            "tableName": "row",
            "elms": [
                {
                    "name": "name",
                    "value": "__________________________"
                },
                {
                    "name": "format",
                    "value": "string"
                },
                {
                    "name": "length",
                    "value": 15
                },
                {
                    "name": "active",
                    "value": true
                }
            ]
        }
    ]

Thanks in Advance.

EDIT: To debug more I removed the condition on tableName all together just to see, if the basic condition on name is working or not, seems like that itself is not working. Could it be that the way I have represented properties.elms.items.properties.name is incorrect?

{
  "properties": {
    "elements": {
      "type": "array",
      "items": {
        "$ref": "#arrayElement"
      },
      "minItems": 1
    }
  },
  "definitions": {
    "arrayElement": {
      "$id": "#arrayElement",
      "type": "object",
      "required": ["tableName"],
      "properties": {
        "tableName": {
          "type": "string"
        },
        "elms": {
          "type": "array",
          "items": {
            "type": "object",
            "required": ["name", "value"],
            "properties": {
              "name": {
                "type": "string"
              },
              "value": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "number"
                  },
                  {
                    "type": "boolean"
                  }
                ]
              }
            }
          },
          "minItems": 0
        },
        "ele2": {
          "type": "object",
          "$ref": "#objectElement"
        },
        "ele3": {
          "type": "array",
          "items": {
            "$ref": "#arrayElement"
          },
          "minItems": 0
        }
      },
      "allOf": [
        {
          "if": {
            "properties": {
              "elms": {
                "items": {
                  "properties": {
                    "name": {
                      "const": "name"
                    }
                  }
                }
              }
            }
          },
          "then": {
            "properties": {
              "elms": {
                "items": {
                  "properties": {
                    "value": {
                      "type": "string",
                      "pattern": "^[A-Za-z][A-Za-z0-9_.#/-]*$"
                    }
                  }
                }
              }
            }
          },
          "else": {
            "properties": {
              "elms": {
                "items": {
                  "properties": {
                    "value": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "number"
                        },
                        {
                          "type": "boolean"
                        }
                      ]
                    }
                  }
                }
              }
            }
          }
        }
      ]
    }
  }
}

EDIT -> Schema after Jason’s suggestion.

"allOf": [
                {
                    "if": {
                        "properties": {
                            "tableName": {
                                "not": { "const": "header" }
                            },
                            "elms": {
                                "type": "array",
                                "items": {
                                    "type": "object",
                                    "properties": {
                                        "name": { "const": "name" }
                                    },
                                    "required": ["name"]
                                }
                            }
                        },
                        "required": ["tableName", "elms"]
                    },
                    "then": {
                        "properties": {
                            "elms": {
                                "items": {
                                    "properties": {
                                        "value": {
                                            "type": "string",
                                            "pattern": "^[A-Za-z][A-Za-z0-9_.#/-]*$"
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            ]

2

Answers


  1. Chosen as BEST ANSWER

    I managed to do it by segregating the if conditions.

    Would like to thank Jason for guiding me to the solution.

    The "if" and "then" clauses seem to check both the tableName and the elms array, but since I am working with arrays and objects within arrays, I need to apply conditions individually inside the items definition for elms.

    {
      "properties": {
        "elements": {
          "type": "array",
          "items": {
            "$ref": "#arrayElement"
          },
          "minItems": 1
        }
      },
      "definitions": {
        "arrayElement": {
          "$id": "#arrayElement",
          "type": "object",
          "required": ["tableName"],
          "properties": {
            "tableName": {
              "type": "string"
            },
            "elms": {
              "type": "array",
              "items": {
                "type": "object",
                "required": ["name", "value"],
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "value": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "number"
                      },
                      {
                        "type": "boolean"
                      }
                    ]
                  }
                }
              },
              "minItems": 0
            }
          },
          "allOf": [
            {
              "if": {
                "properties": {
                  "tableName": {
                    "not": { "const": "header" }
                  }
                }
              },
              "then": {
                "properties": {
                  "elms": {
                    "items": {
                      "if": {
                        "properties": {
                          "name": { "const": "name" }
                        },
                        "required": ["name"]
                      },
                      "then": {
                        "properties": {
                          "value": {
                            "type": "string",
                            "pattern": "^[A-Za-z][A-Za-z0-9_.#/-]*$"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          ]
        }
      }
    }
    

  2. Your conditionals are way more complicated than they need to be.

    Now if the value of name is ‘name’ then it’s value pair should follow a regex validation, except for 1 particular scenario if the tableName where these are being added is header, in that case it should not follow this regex pattern.

    You can express this condition as a single schema.

    {
      "type": "object",
      "properties": {
        "tableName": {
          "not": { "const": "header" }
        },
        "elms": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "name": { "const": "name" }
            },
            "required": ["name"]
          }
        }
      },
      "required": ["tableName", "elms"]
    }
    

    That’s your if schema. You’re then schema is correct. You don’t need else. No need for nesting.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search