2
votes

I am trying to create a complex schema that will check for the value of a property and then validate according to the value of that same property. I am wondering if it's possible to use $ref and allOf in the same schema and if so, how? I am having some trouble getting this to work. It may be important to note that I am using AJV. Please see my code below

{ 
  "$ref": "#/definitions/Welcome",
  "definitions": {
    "Welcome": {
      "properties": {
        "auth": {
          "type": "string",
          "enum": ["oauth1","oauth2"]
        },
        "environment": {
          "$ref": "#/definitions/Environment"
        }
      }
    },
    "Environment": {
      "properties": {
        "dev": {
          "type": "object"
        }
      }
    },
    "Oauth1": {
      "type": "object",
      "properties": {
        "temporary_credentials": {
          "type": "string"
        }
      }
    },
    "Oauth2": {
      "type": "object",
      "properties": {
        "auth_url": {
          "type": "string"
        }
      }
    }
  },
  "allOf": [
    {
      "if": {
        "auth": {
          "const": "oauth1"
        }
      },
      "then": {
        "environment": {
          "dev": {
            "$ref": "#/definitions/Oauth1
          }
        }
      }
    },
    {
      "if": {
        "auth": {
          "const": "oauth2"
        }
      },
      "then": {
        "environment": {
          "dev": {
            "$ref": "#/definitions/Oauth2
          }
        }
      }
    }
  ]
}

A sample json input to be validated against this schema would be something like this

{
  "auth": "oauth1",
  "environment": {
    "dev": {
      "temporary_credentials": "xyzzy"
    }
  }
}

I feel like there might be an error in my "then" statements or simply the placement of the allOf. The error I would get is something like this "$ref: keywords ignored in schema at path "#"".

1
@gregsdennis mine is using "if" and "then" with "$ref" thanks for your input thoughbegprog
It doesn't matter if you're using a $ref or an inline schema; the logic (and the solution) is the the same. Don't use *Of and if/then/else together.gregsdennis
Additionally, the schemas inside the then blocks need some properties callouts.gregsdennis
@gregsdennis why can't allOf and if/then/else be used together? I use it in my schemas; when I have a list of if/thens I wrap it in an allOf and never had problems with that.Erwin Bolwidt

1 Answers

2
votes

In schema version up to and including draft7, once you use "$ref", all other keywords in that level of the schema are ignored. That's what the error is telling you: because you used $ref, other keywords are ignored.

If you only want to use a $ref at the root level, the trick is to wrap it in an "allOf".

But since you already have an allOf at the root level, you can just add the $ref as another branch of the allOf and it will work.

That would look like:

"allOf": [
{
  "$ref": "#/definitions/Welcome",
},
{
  "if": {
    "auth": {
      "const": "oauth1"
    }
    etc.

Note: in the schema you posted, you have two unclosed strings "#/definitions/Oauth1 and "#/definitions/Oauth2. If you had that in your real schema it would be invalid JSON.