json-schema-org / json-schema-spec

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

Why does draft 7 sometimes use `format: regex` without `type: string`? #1405

Closed ahl closed 1 year ago

ahl commented 1 year ago

The use of regex as a format seems inconsistent:

with type https://github.com/json-schema-org/json-schema-spec/blob/567f768506aaa33a38e552c85bf0586029ef1b32/schema.json#L93-L96

without type https://github.com/json-schema-org/json-schema-spec/blob/567f768506aaa33a38e552c85bf0586029ef1b32/schema.json#L129

Is "type": "string" optional in this case? If so, why does the former case include it? If not, is the latter case a bug?

Thanks.

aha79 commented 1 year ago

At least the current draft section 7.1 says

A format attribute can generally only validate a given set of instance types. If the type of the instance to validate is not in this set, validation for this format attribute and instance SHOULD succeed.

Which means

{ "format": "regex" } will allow the types int, number, null, array, boolean and object. Only if the type is string and the format is not a regex it will yield false.

Not sure if this behavior was different in past drafts (I guess not), so I would say a {"type": "string"} is missing here.

Side note: This behavior is imminent to many if not all jsonschema attributes. Because of this the (hypothetical) format-wise negation ("a format which is not a regex"), is not just a simple "not" around "format", but actually requires the type to be included: {"format": "non-regex"} <=> {"not": { "format": "regex", "type": "string" }

jdesrosiers commented 1 year ago

There are some reasons you might want to leave out "type": "string". In the example given, the schema is used with the propertyNames keyword. Property names in a JSON object are always strings. They can't be anything else. Therefore, including "type": "string" is superfluous.

Another reason you might want to leave out "type": "string" is when doing schema composition. Here's an example.

{
  "type": "string",
  "allOf": [
    { "pattern": "^a" },
    { "pattern": "b$" }
  ]
}

Here, the schemas with pattern don't need "type": "string" because"type": "string"` has already been applied to the instance.

ahl commented 1 year ago

There are some reasons you might want to leave out "type": "string". In the example given, the schema is used with the propertyNames keyword. Property names in a JSON object are always strings. They can't be anything else. Therefore, including "type": "string" is superfluous.

This is a great point. Thank you!