Skip to content
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

could certain schemas derived from enums more precisely use oneOf? #98

Closed
ahl opened this issue Aug 18, 2021 · 5 comments · Fixed by #108
Closed

could certain schemas derived from enums more precisely use oneOf? #98

ahl opened this issue Aug 18, 2021 · 5 comments · Fixed by #108

Comments

@ahl
Copy link
Contributor

ahl commented Aug 18, 2021

When writing an SDK generator, we noticed that schemas derived from enums use anyOf for complex variants (and enum for unit variants). This seems necessary in some cases, for example:

#[derive(JsonSchema)]
#[serde(untagged)]
pub enum E {
    ThingA { a: String },
    ThingB { a: String },
}

i.e. where the variants literally cannot be disambiguated. In such a case I don't believe that oneOf would be satisfiable since two subschemas would be identical.

However with tagged enums (external, internal, or adjacent) would it be reasonable to change anyOf to oneOf? For example in this output of the type above, removing the untagged directive:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "E",
  "anyOf": [
    {
      "type": "object",
      "required": [
        "ThingA"
      ],
      "properties": {
        "ThingA": {
          "type": "object",
          "required": [
            "a"
          ],
          "properties": {
            "a": {
              "type": "string"
            }
          }
        }
      },
      "additionalProperties": false
    },
    {
      "type": "object",
      "required": [
        "ThingB"
      ],
      "properties": {
        "ThingB": {
          "type": "object",
          "required": [
            "a"
          ],
          "properties": {
            "a": {
              "type": "string"
            }
          }
        }
      },
      "additionalProperties": false
    }
  ]
}

In this case, where each subschema is mutually exclusive, I believe that anyOf and oneOf are equivalent. It would, however, be more explicit to use oneOf and, as noted earlier, it would simplify our particular use case of SDK generation.

If this seems like a reasonable change I'd be happy to submit a PR, but I wanted to check in first.

@jhoobergs
Copy link

What do you think of #96 ?

@ahl
Copy link
Contributor Author

ahl commented Aug 26, 2021

@jhoobergs I can see what it's useful for your use case, but I don't really like it for mine. I'd like to be able to generate a client SDK from the OpenAPI spec and I'd like a more direct mapping back into Rust enums. I think a oneOf would be a simpler mechanism. In particular, I believe the approach you've taken loses the association between the given variant and the valid data payload.

@GREsau
Copy link
Owner

GREsau commented Sep 19, 2021

However with tagged enums (external, internal, or adjacent) would it be reasonable to change anyOf to oneOf?

Yes that sounds reasonable, and I don't think it would be difficult to implement. I'll take a look when I get some more time - I'd also accept this as a PR

ahl added a commit to ahl/schemars that referenced this issue Sep 19, 2021
@ahl
Copy link
Contributor Author

ahl commented Sep 19, 2021

Thanks! I submitted as #108

@GREsau
Copy link
Owner

GREsau commented Sep 26, 2021

This behaviour is now available in v0.8.6

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants