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

Discriminated Sum/Union/Choice types #48

Open
beached opened this issue Jun 22, 2023 · 6 comments
Open

Discriminated Sum/Union/Choice types #48

beached opened this issue Jun 22, 2023 · 6 comments

Comments

@beached
Copy link

beached commented Jun 22, 2023

Im not sure if this is in focus yet, but when attempting to fail at using JSON Schema as an IDL, one of the biggest issues was explicitly mapping a sum type to it's discriminator. Yes there is a must exist relationship, but it didn't help with things like the "type" member having a value of X and that means the "value" member must be a Foo. This was in regard to using C++, which has language/library support for this via the variant type.

The tags can be in many places in many JSON document in the wild though. Commonly it is a submember of the current value/type, it is a member at the same level, or the existence of a member/key(using them synonymously) at those levels too. But other forms exist too.

@gregsdennis
Copy link
Member

Thanks. We do need this issue. I haven't completed my notes on polymorphism yet, which is why I hadn't created one. It's not quite the same in languages as unions, but I think they're going to end up being quite related in their JSON Schema representations.

I'll try to finish up my notes. I might open a new issue for it, but I'll link to this one.

@gregsdennis
Copy link
Member

Discrinated unions represent that an object must conform to one of multiple schemas. I think the natural choice to represent this concept is oneOf (or anyOf if it can be shown that the options are distinct).

Thinking about it some more, I don't think that this concept interacts with polymorphism all that much. I think they're separate ideas.

@beached
Copy link
Author

beached commented Jul 9, 2023

The discriminators relationship with the union is the issue. Representing the tag/discriminator is normal, as is each of the alternatives. But their relationship can take many forms too.

@gregsdennis
Copy link
Member

@beached can you provide an example? I'm not sure I follow.

@beached
Copy link
Author

beached commented Jul 9, 2023

The simplest is something like

[
{ 
  "type": 2
  "value": "Hello"
},
{
  "type": 0
  "value": { "name": "foo" }
}
]

where the member "type" tells us which of the oneOf types that "value" is. There is some complexity in the wild in where that discriminator is located too. It may also tell us what the rest of the sub-members of the class will be formed too. This is similar to sockets in C where one first peeks at what the socktype member is, or a versioned class where a member like version tells us what the structure of the whole class is.

@to-miz
Copy link

to-miz commented Dec 30, 2023

This is also the biggest issue I had when trying to use JSON Schema to generate code. The problem is, that for JSON Schema there is no need to keep track of a "type" to be able to validate a discriminated union (mostly).
The instance that @beached posted, could be validated with the following:

{
  "type": "array",
  "items": {
    "oneOf": [
      {
        "type": "object",
        "properties": {
          "type": { "const": 2 },
          "value": { "type": "string" }
        }
      },
      {
        "type": "object",
        "properties": {
          "type": { "const": 0 },
          "value": { "type": "object" }
        }
      }
    ]
  }
}

But mostly, no one writes JSON Schemas like these, unless the Schema is generated from source code.

Here is how OpenApi solves this problem and I think they found a very nice solution https://swagger.io/docs/specification/data-models/inheritance-and-polymorphism/
Especially the part of "Mapping Type Names", it means JSON Schema validators can just ignore the discriminator if they don't understand it since validation only requires that oneOf or anyOf pass.

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

No branches or pull requests

3 participants