json-schema-org / json-schema-spec

The JSON Schema specification
http://json-schema.org/
Other
3.43k stars 251 forks source link

pattern matching key/value strings with propertyDependencies / how to require properties with a match? #1511

Open jeremyfiel opened 1 month ago

jeremyfiel commented 1 month ago

I'm late to the party for this one but I have a couple things I'd like clarification on:

This keyword specifies subschemas that are evaluated if the instance is an object and contains a certain property with a certain string value.

Because only string values are supported, should this text indicate the property value should be a constant string rather than a certain string? That sounds very wishy-washy and generic.


Can this keyword take a patternProperties or some variation of pattern matching a key and value as a key lookup rather than a constant?

Not sure if this makes sense or not

patternProperties

{
  "propertyDependencies": {
    "patternProperties": {
      "Code$": {
        "patternProperties": {
          ".*taxable.*": {
            "$ref": "#/$defs/itemSchemaWithTax"
          }
        }
      }
    }
  },
  "$defs": { "itemSchemaWithTax": {}}
}

if/then

{
    "if": {
        "required": ["itemCode"],
        "properties": {"itemCode": {
                "const": "taxable"
            }
        }
    },
    "then": {
        "required": ["itemPrice"],
        "properties": {"itemPrice": {
                "$ref": "#/$defs/itemSchemaWithTax"
            }
        }
    },
    "$defs": {
        "itemSchemaWithTax": {}
    }
}

instance

{
"itemCode": "taxable",
"itemPrice": {}
}

I also noticed there isn't a concise way to require something with propertyDependencies in the same manner as "then": { "required": ["something"]}

gregsdennis commented 1 month ago

I think the priority was on providing a discriminator-type mechanism, where you have a defined "discriminator" property that can be one of several anticipated values, rather than providing a general solution.

With this in mind, I'm not sure that pattern matching is really in the scope of the problem that propertyDependencies is trying to solve.

But that's my initial impression. Others are welcome to voice their opinions as well.

jdesrosiers commented 1 month ago

There was a lot of discussion about supporting matching beyond simple string matching, especially other types like booleans or numbers. Ultimately, it's a balance between easy of use and expressiveness. One of the reasons we think people don't use if/then in these cases as much as they should is that it's verbose and complicated. We wanted something that was simple enough that people would actually want to use it and the syntax becomes a lot more complicated once we start trying to support more things.

Not sure if this makes sense or not

That example isn't making sense to me.

I also noticed there isn't a concise way to require something with propertyDependencies in the same manner as "then": { "required": ["something"]}

Sure there is,

"propertyDependencies": {
  "foo": {
    "bar": { "required": ["something"] }
  }
}
gregsdennis commented 2 weeks ago

@jeremyfiel are you satisfied with this response, or do you want to continue pursuing this as part of the propertyDependencies proposal?

jeremyfiel commented 2 weeks ago

Yep I'm all good

Just the comment about the text remains outstanding.

gregsdennis commented 2 weeks ago

I expect you mean this:

This keyword specifies subschemas that are evaluated if the instance is an object and contains a certain property with a certain string value.

Because only string values are supported, should this text indicate the property value should be a constant string rather than a certain string? That sounds very wishy-washy and generic.

I'm not sure. Using the word "constant" to me implies that the property needs to be a constant as if the schema used the const keyword, which, yes, the alternative does, but I don't think that's what's happening here.

Maybe...

This keyword specifies subschemas that are evaluated if an object instance contains the indicated property with the indicated string value.

That's not much better.

jeremyfiel commented 2 weeks ago

Ya I was thinking the same about "a certain string" being very generic. I don't have a better suggestion though haha