Home > Back-end >  JSON Schema | Only allow one object to have boolean property set to true
JSON Schema | Only allow one object to have boolean property set to true

Time:01-11

I have JSON data that looks like this:

{
  "Plugins": {
    "TestPlugin": {
      "enabled": true,
      "auth": {
        "basic": {
          "username": "MyUsername",
          "password": "MyPassword",
          "enabled": true
        },
        "oauth": {
          "token": "MyToken",
          "enabled": false
        }
      }
    },
    "AnotherTestPlugin": {
      "enabled": true,
      "auth": {
        "basic": {
          "username": "MySecondUsername",
          "password": "MySecondPassword",
          "enabled": true
        },
        "oauth": {
          "token": "MySecondToken",
          "enabled": true
        }
      }
    }
  }
}

The schema (Version 2020-12) that should be used for validation currently looks like this:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "Plugins": {
      "type": "object",
      "properties": {
        "TestPlugin": {
          "type": "object",
          "properties": {
            "enabled": {
              "type": "boolean"
            },
            "auth": {
              "type": "object",
              "properties": {
                "basic": {
                  "type": "object",
                  "properties": {
                    "username": {
                      "type": "string"
                    },
                    "password": {
                      "type": "string"
                    },
                    "enabled": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "username",
                    "password",
                    "enabled"
                  ]
                },
                "oauth": {
                  "type": "object",
                  "properties": {
                    "token": {
                      "type": "string"
                    },
                    "enabled": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "token",
                    "enabled"
                  ]
                }
              },
              "required": [
                "basic",
                "oauth"
              ]
            }
          },
          "required": [
            "enabled",
            "auth"
          ]
        },
        "AnotherTestPlugin": {
          "type": "object",
          "properties": {
            "enabled": {
              "type": "boolean"
            },
            "auth": {
              "type": "object",
              "properties": {
                "basic": {
                  "type": "object",
                  "properties": {
                    "username": {
                      "type": "string"
                    },
                    "password": {
                      "type": "string"
                    },
                    "enabled": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "username",
                    "password",
                    "enabled"
                  ]
                },
                "oauth": {
                  "type": "object",
                  "properties": {
                    "token": {
                      "type": "string"
                    },
                    "enabled": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "token",
                    "enabled"
                  ]
                }
              },
              "required": [
                "basic",
                "oauth"
              ]
            }
          },
          "required": [
            "enabled",
            "auth"
          ]
        }
      }
    }
  },
  "required": [
    "Plugins"
  ]
}

As you can see, each plugin contains an auth object. The auth object contains the available ways of authentication that the corresponding plugin support. Each authentication method can be enabled/disabled with the corresponding enabled property that must be present and contain a boolean.

It is important that for each plugin, only one of the available authentication methods is enabled (boolean: true), the other ones must be disabled by having the enabled property set to false.

I looked through the JSON Schema specifications but cannot really figure out how to achieve this.

Thanks in advance!

CodePudding user response:

It is important that for each plugin, only one of the available authentication methods is enabled (boolean: true), the other ones must be disabled by having the enabled property set to false.

You can do this in draft2020-12 with the oneOf property: in pseudocode, it would be "one of: - basic auth has enabled=true and the other auths have enabled=false; - oath auth has enabled=true; ..." That is:

"oneOf": [
  {
    "properties": {
      "basic": {
        "properties": {
           "enabled": { "const": true }
        }
      }
    },
    "additionalProperties": {
      "properties": {
        "enabled": { "const": false }
      }
    }
  },
  ... same, but for the other auth types
]

You could also use if/then/else clauses to do the same thing, if you find that more readable: in pseudocode, that would be "allOf: [if basic has enabled=true, then oauth has enabled=false and have enabled=false; if oauth has enabled=true then ...]"

If the auth types can be anything, then it's trickier, since you can't itemize the names in oneOf clauses, but it will be possible in the next draft, where the "contains" keyword is expanded to also include objects. At that time, you can say "auth contains an object with enabled=true, and there can be a maximum of one of them" (i.e. maxContains=1).

CodePudding user response:

Can you redefine to include a enabledAuthenticationMethod property? That property would be set to the name of the enabled authentication method.

Depending on your use case, you could still include the enabled attribute if you really want, but I'm not sure of any value to it.

I don't see a solution either (via a schema) for validating your current use case.

  •  Tags:  
  • Related