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.

Test-Json ignores if else statement in json-schema

See original GitHub issue

Issue: Test-Json scripts overlooks/ ignores “if then else” conditions in json schema for attribute checks.

Steps to reproduce

Json schema:

{
    "$schema": "http://json-schema.org/draft-07/schema#",
    "$id": "http://example.com/example.json",
    "type": "object",
    "title": "The root schema",
    "description": "The root schema comprises the entire JSON document.",
    "required": [
        "sqlConfig"
    ],
    "properties": {
        "sqlConfig": {
            "$id": "#/properties/sqlConfig",
            "type": "array",
            "title": "The sqlConfig schema",
            "description": "Contains sql configuration information",
            "uniqueItems": true,
            "additionalItems": true,
            "items": {
                "$id": "#/properties/sqlConfig/items",
                "anyOf": [
                    {
                        "$id": "#/properties/sqlConfig/items/anyOf/0",
                        "type": "object",
                        "title": "The first anyOf schema",
                        "description": "SQL properties",
                        "if": {
                            "properties": {
                                "family": {
                                    "pattern": "^(?i)(azuresql)$"
                                }
                            }
                        },
                        "then": {
                            "required": [
                                "sku",
                                "family",
                                "type",
                                "keyvault",
                                "serverName",
                                "administratorLogin"
                            ]
                        },
                        "else": {
                            "required": [
                                "sku",
                                "family",
                                "keyvault",
                                "serverName",
                                "administratorLogin"
                            ]
                        },
                        "properties": {
                            "sku": {
                                "$id": "#/properties/sqlConfig/items/anyOf/0/properties/sku",
                                "type": "object",
                                "title": "The sku schema",
                                "description": "database sku",
                                "required": [
                                    "capacity",
                                    "name"
                                ],
                                "properties": {
                                    "capacity": {
                                        "$id": "#/properties/sqlConfig/items/anyOf/0/properties/sku/properties/capacity",
                                        "type": "integer",
                                        "title": "capacity",
                                        "description": " # In Vcores for GP, BC, HS. In DTU for others."
                                    },
                                    "name": {
                                        "$id": "#/properties/sqlConfig/items/anyOf/0/properties/sku/properties/name",
                                        "type": "string",
                                        "title": "sku service objective name",
                                        "description": "ServiceObjectiveName - Get-AzSqlServerServiceObjective -Location <location>"
                                    }
                                },
                                "additionalProperties": false
                            },
                            "family": {
                                "$id": "#/properties/sqlConfig/items/anyOf/0/properties/family",
                                "type": "string",
                                "title": "database family",
                                "pattern": "^(?i)(azuresql|postgresql|mariadb|mysql)$",
                                "description": "type of database server"
                            },
                            "firewallRules": {
                                "$id": "#/properties/sqlConfig/items/anyOf/0/properties/firewallRules",
                                "type": "array",
                                "title": "The firewallRules schema",
                                "description": "firewall rules for the database",
                                "uniqueItems": true,
                                "additionalItems": true,
                                "items": {
                                    "$id": "#/properties/sqlConfig/items/anyOf/0/properties/firewallRules/items",
                                    "anyOf": [
                                        {
                                            "$id": "#/properties/sqlConfig/items/anyOf/0/properties/firewallRules/items/anyOf/0",
                                            "type": "object",
                                            "title": "The first anyOf schema",
                                            "description": "An explanation about the purpose of this instance.",
                                            "required": [
                                                "endIpAddress",
                                                "startIpAddress"
                                            ],
                                            "properties": {
                                                "endIpAddress": {
                                                    "$id": "#/properties/sqlConfig/items/anyOf/0/properties/firewallRules/items/anyOf/0/properties/endIpAddress",
                                                    "type": "string",
                                                    "format": "ipv4",
                                                    "title": "The endIpAddress schema",
                                                    "description": "An explanation about the purpose of this instance."
                                                },
                                                "startIpAddress": {
                                                    "$id": "#/properties/sqlConfig/items/anyOf/0/properties/firewallRules/items/anyOf/0/properties/startIpAddress",
                                                    "type": "string",
                                                    "format": "ipv4",
                                                    "title": "The startIpAddress schema",
                                                    "description": "An explanation about the purpose of this instance."
                                                }
                                            },
                                            "additionalProperties": false
                                        }
                                    ]
                                }
                            },
                            "keyvault": {
                                "$id": "#/properties/sqlConfig/items/anyOf/0/properties/keyvault",
                                "type": "object",
                                "title": "The keyvault schema",
                                "description": "An explanation about the purpose of this instance.",
                                "required": [
                                    "serviceTag",
                                    "passwordsecretName"
                                ],
                                "properties": {
                                    "serviceTag": {
                                        "$id": "#/properties/sqlConfig/items/anyOf/0/properties/keyvault/properties/serviceTag",
                                        "type": "string",
                                        "title": "The serviceTag schema",
                                        "description": "An explanation about the purpose of this instance."
                                    },
                                    "passwordsecretName": {
                                        "$id": "#/properties/sqlConfig/items/anyOf/0/properties/keyvault/properties/passwordsecretName",
                                        "type": "string",
                                        "title": "The passwordsecretName schema",
                                        "description": "An explanation about the purpose of this instance."
                                    }
                                },
                                "additionalProperties": false
                            },
                            "serverName": {
                                "$id": "#/properties/sqlConfig/items/anyOf/0/properties/serverName",
                                "type": "string",
                                "title": "The serverName schema",
                                "description": "An explanation about the purpose of this instance."
                            },
                            "databaseNames": {
                                "$id": "#/properties/sqlConfig/items/anyOf/0/properties/databaseNames",
                                "type": "array",
                                "title": "The databaseNames schema",
                                "description": "An explanation about the purpose of this instance.",
                                "uniqueItems": true,
                                "additionalItems": true,
                                "items": {
                                    "$id": "#/properties/sqlConfig/items/anyOf/0/properties/databaseNames/items",
                                    "anyOf": [
                                        {
                                            "$id": "#/properties/sqlConfig/items/anyOf/0/properties/databaseNames/items/anyOf/0",
                                            "type": "string",
                                            "title": "The first anyOf schema",
                                            "description": "An explanation about the purpose of this instance."
                                        }
                                    ]
                                }
                            },
                            "type": {
                                "$id": "#/properties/sqlConfig/items/anyOf/0/properties/type",
                                "type": "string",
                                "title": "The type schema",
                                "description": "An explanation about the purpose of this instance."
                            },
                            "administratorLogin": {
                                "$id": "#/properties/sqlConfig/items/anyOf/0/properties/administratorLogin",
                                "type": "string",
                                "title": "The administratorLogin schema",
                                "description": "An explanation about the purpose of this instance."
                            }
                        },
                        "additionalProperties": false
                    }
                ]
            }
        }
    },
    "additionalProperties": false
}

Json file:

{
  "sqlConfig": [
    {
      "keyvault": {
        "passwordsecretName": "databasepassword",
        "serviceTag": "kvaultcorerg"
      },
      "sku": {
        "name": "free",
        "capacity": 5
      },
      "administratorLogin": "databaseowner",
      "serverName": "commonserver"
    }
  ]
}

Imported above files and ran a test against json file. The output is true that JSON matches SCHEMA but expectation with test is to fail as FAMILY and TYPE are missing.

  
  PS > $schema = Get-Content -raw $SchemaFile
  PS > $json | Test-Json -Schema $schema -Verbose
  True

Expected behavior

FALSE.
Required properties are missing from object: family, type.

Actual behavior

  • If else validation is overlooked. It doesn’t look at anything “required” and everything passed. Ideally it should fail because family and type are missing.

if do same validation through other validation tools, i get correct response.

image

image

Environment data

PS> $PSVersionTable

Name                           Value
----                           -----
PSVersion                      7.0.0
PSEdition                      Core
GitCommitId                    7.0.0
OS                             Linux 5.3.0-1035-azure #36-Ubuntu SMP Thu Aug 6 09:21:33 UTC 2020
Platform                       Unix
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0

Issue Analytics

  • State:open
  • Created 3 years ago
  • Comments:5 (1 by maintainers)

github_iconTop GitHub Comments

1reaction
vexx32commented, Aug 25, 2020
0reactions
gregsdenniscommented, Jul 11, 2023

The JSON Schema implementation has been recently updated to JsonSchema.Net and is available in the latest Powershell snapshot. Please retest this to see if it is still a problem.

https://json-everything.net/json-schema reports that the instance fails, with the output including this report:

{
  "valid": false,
  "evaluationPath": "/properties/sqlConfig/items/anyOf/0/then",
  "schemaLocation": "http://example.com/example.json#/properties/sqlConfig/items/anyOf/0/then",
  "instanceLocation": "/sqlConfig/0",
  "errors": {
    "required": "Required properties [\"family\",\"type\"] were not present"
  }
}

I believe this was the expected outcome.

Read more comments on GitHub >

github_iconTop Results From Across the Web

JSON Schema not working as expected with if/then/else
1 Answer. Your conditionals don't have any "else" clauses -- so if the if part is false, the else will default to true...
Read more >
then":"else" ignored when validating JSON with schema ...
I have a JSON schema that contains some conditional statements. ... "if":"then":"else" ignored when validating JSON with schema #1494.
Read more >
A Vocabulary for Structural Validation of JSON
Similarly, annotations within a failing branch of a "oneOf", "anyOf", "then", or "else" MUST be ignored even when the instance successfully validates against ......
Read more >
Applying Subschemas Conditionally
If -Then-Else​​ If if is valid, then must also be valid (and else is ignored.) If if is invalid, else must also be...
Read more >
A Vocabulary for Structural Validation of JSON
If the value of "type" is a string, then an instance validates successfully if its type matches the type represented by the value...
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