-
Notifications
You must be signed in to change notification settings - Fork 9.1k
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
Reference objects don't combine well with “nullable” #1368
Comments
@Rinzwind I use This is how boolean flags like See also #1389 for |
About the example given in the original post: if we're interpreting File:
type: object
properties:
name:
type: string
dataFork:
$ref: '#/components/schemas/Fork'
resourceFork:
nullable: true
anyOf:
- $ref: '#/components/schemas/Fork'
Fork:
type: object
description: Information aspect of a file... I added a 'Fork' stub schema to illustrate. Fork itself is not nullable, it requires an object value. (And BTW, even if Fork didn't specify a In the File schema, resourceFork has So I think the first attempted schema in the original post is closer to the mark. But we have to do something kind of awkward to allow either File:
type: object
properties:
name:
type: string
dataFork:
$ref: '#/components/schemas/Fork'
resourceFork:
oneOf:
- $ref: '#/components/schemas/Fork'
- $ref: '#/components/schemas/NullValue'
Fork:
type: object
description: Information aspect of a file...
NullValue:
# Allow null values.
nullable: true
# Disallow any non-null value.
not:
anyOf:
- type: string
- type: number
- type: boolean
- type: object
- type: array
# Array schema must specify items, so we'll use an
# empty object to mean arrays of any type are included.
items: {} It might be cleaner to start with a nullable Fork object, and restrict it to non-null as needed: File:
type: object
properties:
name:
type: string
dataFork:
allOf:
- nullable: false
- $ref: '#/components/schemas/Fork'
resourceFork:
$ref: '#/components/schemas/Fork'
Fork:
type: object
nullable: true
description: Information aspect of a file... |
I'm not sure that's right. The JSON schema validation specification says that “validation keywords typically operate independent of each other” (section 4.3) (*), but then makes some exceptions. The OpenAPI Specification 3.0.2 isn't exactly clear on how it defines “nullable”, but I think it would have to be an exception too. Otherwise “nullable” would seem to always conflict with other keywords, in particular “type”. For example, consider the schema (*) Section 4.3 in the version of the JSON schema validation specification linked to from the OpenAPI specification 3.0.2. In newer versions, the sentence moved to section 3.1.1.
I hadn't considered that, if your schema “NullValue” is correct and allowed by OpenAPI, that seems like a way of sneaking the easier to understand |
Hi @Rinzwind , I'm one of the current primary editors of the JSON Schema spec (and yes, it's my fault that draft-08 is taking forever to appear 😭 ) What "validation keywords typically operate independently" is that in the majority of cases, each keyword's validation outcome can be determined without examining any other keyword. As of draft-06 and later, that is true of any assertion keyword, such as Some applicator keywords (which apply subschemas and combine their assertion results, rather than producing their own results) do interact. The most notorious being that determining to which properties Sadly, in draft-04 (which is effectively what OAS uses- there's not really a draft-05, it's a long story), the OAS's That's probably more than you wanted to know, but the upshot is that
|
OK, but regardless of the violations of
|
There are discussions in #1389 and #1900 essentially trying to figure out how to interpret
That's how I assumed it worked. But then I dug deeper and now I'm much less certain of how the founding fathers intended We could say that I think we're still waiting to hear from the TSC about this one. |
It's not so clear to me what the alternative interpretation(s) is / are by which any of the following schemas would not allow
I think we can assume that in any interpretation, at least schema 1 should allow |
One of the interpretations under discussion is Taking schema 2 as an example:
It's not limited to that. Interpretation of
The problem with that interpretation is that JSON Schema doesn't have any way of "overriding" a constraint. Constraints can be added, but they can't be taken away. If you really want to introduce "override" as a whole new mechanism in OpenAPI schema, then we have no clean way of translating OpenAPI schemas to JSON Schemas. And in that case, API implementations, tools and libraries can't make use of standard JSON Schema validators; they have to use specialized OAS schema validators. And this mismatch makes for a steeper learning curve for developers moving from one language to the other. That's the gap we're trying to narrow, not just with There is another possible interpretation that doesn't break with JSON Schema: That is much closer to an override. In this case, But there are some issues:
|
Perhaps I'm missing something, but I don't get why that would be counterintuitive? I opened this issue because I wanted to express the JSON schema |
In your case, you knew exactly what you wanted, and the wrapping of your schema into an
Yes, that's right. |
I'm not quite sure I get what you mean, but are you perhaps talking about an example such as the following? “Override” may have been a bad choice of words with respect to an example like this, but I did not mean to imply that this would allow “foo” to be
This is, as far as I get, in keeping with your transformation rule to JSON schema:
The same applies: |
@Rinzwind , I have to get back to my day job. ;-) If I have time, I'll try to parse what you've written here and respond. But IMO, there is no happy solution that preserves |
Oh sure, no problem, and I would also prefer for OpenAPI to stick to JSON schema's Musings: the only possible benefit I see to “nullable” is that it makes it very easy to determine whether the instance
Keep in mind that “nullable” is implicitly included in every OpenAPI schema with default value This would imply though that the OpenAPI schema We could instead use these two transformation rules:
But that would imply losing the possible benefit of “nullable”. A schema like |
I hadn't fully grasped what you meant by this. I'm not sure I do now; if you find the time to comment, I was wondering whether the following correctly reflects that interpretation w.r.t. to
|
Yes, exactly. :-) In the fourth example, |
Ok, I think I got it then. I think I have to put the question back to @handrews, who was previously the first one to respond to this issue, saying:
@handrews: I'm not sure you intended to imply that the example I gave (opening comment of this issue) expresses (as intended) that both “dataFork” and “resourceFork” contain a Fork, except that “resourceFork” can also be Using a simpler example, I think the question is similar to whether this OpenAPI schema:
… is equivalent to this JSON schema: (allows
… or to this one: (does not allow
|
nullable works differently for 'anyOf' and this commit introduces changes to reflect this OAI/OpenAPI-Specification#1368 (comment).
nullable works differently for 'anyOf' and this commit introduces changes to reflect this OAI/OpenAPI-Specification#1368 (comment).
nullable works differently for 'anyOf' and this commit introduces changes to reflect this OAI/OpenAPI-Specification#1368 (comment).
…oneOf, therefore allow null as part of the other sub-schemas. See OAI/OpenAPI-Specification#1368 and related issues.
This is somewhat undefined behavior [1][2], however, it worked until openapi-core 0.15.x. Demonstrate this, pending a fix. [1] https://stackoverflow.com/a/48114924/613428 [2] OAI/OpenAPI-Specification#1368 Signed-off-by: Stephen Finucane <stephen@that.guru>
This is somewhat undefined behavior [1][2], however, it worked until openapi-core 0.15.x. Demonstrate this, pending a fix. [1] https://stackoverflow.com/a/48114924/613428 [2] OAI/OpenAPI-Specification#1368 Signed-off-by: Stephen Finucane <stephen@that.guru>
Apparently `nullable` doesn't play well with attribute modifications in OpenAPI 3.0 (apparently better in 3.1?). This is evidenced by validations previously passing against newer versions when it should've been impossible. OAI/OpenAPI-Specification#1368
OpenAPI 3.0 has some unspecified behavior regarding the combination of reference objects with 'nullable' [1]. Despite what random StackOverflow answers [2] suggest, combining nullable with '$ref' still doesn't work. Do what's suggested in the issue reporting this behavior [3] and upgrade to OpenAPI 3.1, allowing us to work around this. [1] OAI/OpenAPI-Specification#1368 [2] https://stackoverflow.com/a/48114924/613428 [3] OAI/OpenAPI-Specification#1368 (comment) Signed-off-by: Stephen Finucane <stephen@that.guru>
That PR was merged into the |
@maRci002 OAS 3.1.0 was released in 2021. That's the status unless I'm missing something about your question. |
@maRci002 we solved the problem by getting rid of the specific-to-OAS The problem had two parts:
|
@handrews, thank you very much for the clarification. However, I have a question about how this would work with reference objects. For example: This configuration: {
"type": "object",
"properties": {
"snippet": {
"type": "object",
"properties": {
"username": {
"type": "string"
}
},
"required": [
"username"
],
"additionalProperties": false
},
"snippet2": {
"allOf": [
{
"$ref": "#/properties/snippet"
}
],
"nullable": true
}
},
"required": [
"snippet",
"snippet2"
],
"additionalProperties": false
} Becomes this? {
"type": "object",
"properties": {
"snippet": {
"type": "object",
"properties": {
"username": {
"type": "string"
}
},
"required": [
"username"
],
"additionalProperties": false
},
"snippet2": {
"type": ["object", "null"],
"$ref": "#/properties/snippet"
}
},
"required": [
"snippet",
"snippet2"
],
"additionalProperties": false
} |
@maRci002 the problem you are encountering is that JSON Schema is a constraint system, not a data definition system. When you want to re-use a schema, you need to start with the most permissive version of the schema, and then add further constraints. So you can start with |
Commenting to trigger email notification: A better example than what I initially wrote above would be adding |
Thank you again; this makes sense. Is it a good practice to register my most permissive version of the schema under |
@maRci002 to make a "snippet2": {
"anyOf": [
{ "$ref": "#/properties/snippet" },
{ "type": "null" }
]
} |
Thank you, but in my case, |
Perhaps more of a question than an issue report, but I am not sure how to combine “nullable” with a reference object; I have the impression they don't combine well?
In Swagger-UI issue 3325 I posted an example with the following schema. The intent is to express that both “dataFork” and “resourceFork” contain a Fork, except that “resourceFork” can also be
null
, but “dataFork” cannot benull
. As was pointed out though, the schema is not in accordance with the OpenAPI v3.0.0 specification, due to the use of JSON Schema's{"type":"null"}
which has not been adopted in OpenAPI.I considered I can instead express the example as follows, which as far as I can tell is at least in accordance with the OpenAPI specification? But the use of “anyOf” with only one schema inside seems clumsy, is there a better way to handle this? Essentially, a better way to combine “nullable” with the reference object?
The text was updated successfully, but these errors were encountered: