-
-
Notifications
You must be signed in to change notification settings - Fork 280
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How to interpret schema with both properties and oneOf? #1529
Comments
@handrews any chance you could chime in? This is blocking bcherny/json-schema-to-typescript#603 |
@bcherny it's been a bit of a heavy month for some of us here. Sorry for missing this. (And BTW, Henry has shifted his focus more towards OpenAPI lately.) This schema is written very strangely, IMO. Let's isolate the parts that are most likely confusing here. {
"oneOf": [
{
"properties": {
"foo": {
"type": "string",
"enum": [ "SqlConnectionInfo" ]
}
}
}
],
"properties": {
"foo": {
"type": "string"
}
}
} JSON Schema operates by declaring constraints on the instance (and locations within it). In this case, there are three constraints on the instance location
If you'll notice, (1) and (3) are the same requirement; it's just specified in two different places. My guess is that this schema was generated using a template that looks something like this:
Then they replace For your original schema, the We are currently working on updating the documentation. We have an open issue to add a recommendation about avoiding the redundancy. |
I can speak to the code generation aspect:
Both of these are correct. "oneOf" doesn't have any special interaction with "properties", both keywords must accept the input, and you can factor out, and distribute in, keywords over oneOf as you would logically expect. All three properties "userName, "password", and "type" will be optional—but when provided, must conform to the given criteria, and for "type" specifically, it must be exactly "SqlConnectionInfo". Does that answer your question? A few things to point out here: the aggregation keywords allOf/anyOf/oneOf are not "useful" unless there's two or more subschemas. Like @gregsdennis points out, such a schema is odd, as it's needlessly complicated. This has some considerations for code generation applications: If it lists zero subschemas, it would be vacuously false; as such it describes the empty set, and would result in a type that cannot contain any values. I'm not aware of any way to notate such a thing. (anyOf is also vacuously false; but allOf is vacuously true.) If it has one subschema, like your example, then allOf=anyOf=oneOf, and you can "factor out" all the keywords: "SqlConnectionInfo": {
"type": "object",
"properties": {
"userName": {
"type": "string",
"description": "User name"
},
"password": {
"type": "string",
"description": "Password credential."
},
"type": {
"type": "string",
"enum": [
"SqlConnectionInfo"
]
}
...
},
...
}, (Also note how "type" becomes redundant in the presence of "enum" or "const".) Finally, when you have two or more subschemas in "oneOf", then you can factor out keywords that all the subschemas have in common, as siblings to oneOf (except to the extent that one keyword affects/is read by another, in which case they must be refactored together; or if the keyword already exists with a different value). This applies for all three oneOf/anyOf/allOf because of how logical AND distributes. Also note that, if I understand correctly, the | operator in TypeScript denotes a union, i.e. anyOf. You can only take anyOf=oneOf when the subschemas are completely disjoint from each other. I will close this out since there's not a specific proposal for the specification, feel free to propose one or continue discussing here, though you may find better support in one of the venues dedicated to usage. |
Thank you both for the great explanations -- that answers my question 🙏. |
I was wondering how to interpret the
SqlConnectionInfo
definition in the Azure JSON-Schema.It looks like this:
Full JSON-Schema: https://schema.management.azure.com/schemas/2017-11-15-privatepreview/Microsoft.DataMigration.json.
Is the right way to interpret this:
SqlConnectionInfo
is an object which may declare keysuserName
,password
, andtype
type
field must be the string literal"SqlConnectionInfo"
Motivation: making sure that https://github.com/bcherny/json-schema-to-typescript/pull/603/files doesn't regress TypeScript typing generation for Azure's JSON-Schema.
Side note: it would be nice if the JSON-Schema Spec and docs more directly talked about how to handle complex schemas like this one, where more than one keyword applies (eg. if this schema definition moved the
oneOf
intotype
's definition, it would be much more clear how to interpret this schema). Or, let me know if I missed it in the docs.The text was updated successfully, but these errors were encountered: