skip to Main Content

please I have a question with regards to json schema. I have a complex model that I am trying to build a schema for in JSON so that I can validate each model created. The condition for a valid model are as follows

  1. in the Json document, there is an array(ArrayElement) which contains list of objects. some of these objects are mandatory while some are not.

  2. for the mandatory objects, the minimum and maximum number must be two(since they are mandatory), they must also be unique, some keys in the object must have diiferent value.

  3. for the optional objects, the maximum occurence must be 4, they must also be unique, some keys in the object must have different value. The occurrence of the optional object in the array can be 0.

  4. if all objects are provided in the array, that means the maximum objects in that arraay should not be more that 6.

  5. no additional object(with another schema) should be allowed except the schema of the two mandatory and optional objects.

  6. no additional Properties should also be allowed in these two objects.

With these conditions, I wrote the following schema to reflect what I am trying to achieve.

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "ArrayElements": {
        "anyOf": [
          {"contains":{
            "properties": {
              "id" : {
                "type" : "string",
                "enum": ["title", "created", "support", "modified"]
              },
              "modelType" : {
                "type": "string",
                "enum": ["Property", "Range", "File"]
              }
            },
            "additionalProperties": false,
            "required": ["id", "modelType"]
          },
            "maxContains": 4,
            "uniqueItems": true
          },
        
          {"contains": {
            "properties": {
              "name": {
                  "type" : "string",
                  "enum": ["Name1","Name2"]
              },
              "modelType": {
                "type" : "string",
                "enum": ["coll"]
            },
              "email" : {
                  "type": "string"
              }
          },
          "additionalProperties": false,
          "required": ["name", "email", "modelType"]
          }, 
          "minContains" : 2,
          "maxContains": 2,
          "uniqueItems": true
          }

        ]
      },
    "modelType": {
      "const": "exampleModelType"
    }
    },
  
  "required": ["modelType"]
    
}

My expected results are as follows:

{
    "ArrayElements":[
    {
        "name" : "Name1",
        "email" : "Hallo",
        "modelType": "coll"
    },

    {
        "name" : "Name2",
        "email" : "Hallo",
        "modelType": "coll"
    }
    ],
    "modelType": "exampleModelType"
}

Should be valid(They represent the mandatory schema) but it not valid

{
    "ArrayElements":[
    {
        "name" : "Name1",
        "email" : "Hallo",
        "modelType": "coll"
    },

    {
        "name" : "Name2",
        "email" : "Hallo",
        "modelType": "coll"
    },
    {   
        "id" : "title",
        "modelType" : "File"
    }
    ],
    "modelType": "exampleModelType"
}

This is valid.

{
    "ArrayElements":[
    {
        "name" : "Name3",
        "email" : "Hallo",
        "modelType": "coll"
    },

    {
        "name" : "Name4",
        "email" : "Hallo",
        "modelType": "coll"
    },
    {   
        "id" : "title",
        "modelType" : "File"
    }
    ],
    "modelType": "exampleModelType"
}

Should be invalid(because Name3 and Name4 are not in the enum values) but it is valid

{
    "ArrayElements":[
    {
        "name" : "Name1",
        "email" : "Hallo",
        "modelType": "coll"
    },

    {
        "name" : "Name2",
        "email" : "Hallo",
        "modelType": "coll"
    },
    {   
        "id" : "title",
        "modelType" : "File"
    },
    {   
        "underfinedKey" : "title",
        "anotherUndefinedKey" : "Hallo"
    }
    ],
    "modelType": "exampleModelType"
}

THis should be invalid because the last object is not a schema that was defined.

2

Answers


  1. Chosen as BEST ANSWER

    After sometime with this problem, I have finally found a way to work on the six requirements. Below is the schema.

    {
      "$schema": "http://json-schema.org/draft-07/schema#",
      "type": "object",
      "properties": {
        "ArrayElements": {
          "type": "array",
          "uniqueItems": true,
          "maxItems": 6,
          "minContains": 2,
          "maxContains": 2,
          "items": {
            "anyOf": [
              {
                "$ref": "#/definitions/optionalItem1"
              },
              {
                "$ref": "#/definitions/mandatoryItem1"
              }
            ]
          },
          "contains": {
            "$ref": "#/definitions/mandatoryItem1"
          }
        },
        "modelType": {
          "const": "exampleModelType"
        }
      },
      "additionalProperties": false,
      "required": [
        "modelType"
      ],
      "definitions": {
        "mandatoryItem1": {
          "properties": {
            "name": {
              "type": "string",
              "enum": [
                "Name1",
                "Name2"
              ]
            },
            "modelType": {
              "type": "string",
              "enum": [
                "coll"
              ]
            },
            "email": {
              "type": "string"
            }
          },
          "additionalProperties": false,
          "required": [
            "name",
            "email",
            "modelType"
          ]
        },
        "optionalItem1": {
          "properties": {
            "id": {
              "type": "string",
              "enum": [
                "title",
                "created",
                "support",
                "modified",
                "Hello"
              ]
            },
            "modelType": {
              "type": "string",
              "enum": [
                "Property",
                "Range",
                "File"
              ]
            }
          },
          "additionalProperties": false,
          "required": [
            "id",
            "modelType"
          ]
        }
      }
    }
    

    The test samples still remain the same plus an additional sample(shown below) that test if two mandatory item actually exist in the object.

    {
      "ArrayElements": [
        {
          "name": "Name1",
          "email": "Hallo",
          "modelType": "coll"
        },
        {   
            "id" : "modified",
            "modelType" : "File"
        }
      ],
      "modelType": "exampleModelType"
    }
    

    This sample will be invalid because it does not satisfy #2 requirement


  2. I believe this should tick all of your boxes.

    {
        "$schema": "https://json-schema.org/draft/2020-12/schema",
        "type": "object",
        "unevaluatedProperties": false,
        "required": [
            "ArrayElements",
            "modelType"
        ],
        "properties": {
            "ArrayElements": {
                "type": "array",
                "maxItems": 6,
                "unevaluatedItems": false,
                "uniqueItems": true,
                "items": {
                    "type": "object",
                    "required": [
                        "modelType"
                    ],
                    "properties": {
                        "modelType": {
                            "type": "string",
                            "enum": [
                                "Property",
                                "Range",
                                "File",
                                "coll"
                            ]
                        }
                    },
                    "anyOf": [
                        {
                            "title": "optional objects",
                            "type": "object",
                            "properties": {
                                "id": {
                                    "type": "string",
                                    "enum": [
                                        "title",
                                        "created",
                                        "support",
                                        "modified"
                                    ]
                                },
                                "modelType": true
                            },
                            "unevaluatedProperties": false,
                            "required": [
                                "id"
                            ]
                        },
                        {
                            "title": "mandatory objects",
                            "type": "object",
                            "properties": {
                                "name": {
                                    "type": "string",
                                    "enum": [
                                        "Name1",
                                        "Name2"
                                    ]
                                },
                                "email": {
                                    "type": "string"
                                },
                                "modelType": true
                            },
                            "unevaluatedProperties": false,
                            "required": [
                                "name",
                                "email"
                            ]
                        }
                    ]
                },
                "allOf": [
                    {
                        "if": {
                            "items": {
                                "properties": {
                                    "modelType": {
                                        "enum": [
                                            "coll"
                                        ]
                                    }
                                }
                            }
                        },
                        "then": {
                            "minItems": 2,
                            "maxItems": 2
                        }
                    },
                    {
                        "if": {
                            "items": {
                                "properties": {
                                    "modelType": {
                                        "enum": [
                                            "Property",
                                            "Range",
                                            "File"
                                        ]
                                    }
                                }
                            }
                        },
                        "then": {
                            "maxItems": 4
                        }
                    }
                ]
            },
            "modelType": {
                "const": "exampleModelType"
            }
        }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search