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

How to create a heterogeneous array of allOf? #137

Closed
ferologics opened this issue Oct 16, 2020 · 6 comments
Closed

How to create a heterogeneous array of allOf? #137

ferologics opened this issue Oct 16, 2020 · 6 comments

Comments

@ferologics
Copy link

I'm trying to figure out a way to represent an array of enum.
Could you point me to an example?

I tried to verify

[
  { "type": "foo", "a": "string" },
  { "type": "bar", "b": 0 }
]

against my schema

{
  "definitions": {
    "foo": { 
      "type": "object",
      "properties": { "a": "string" },
      "required": ["a"]
    },
    "bar": { 
      "type": "object",
      "properties": { "b": "number" },
      "required": ["b"]
    }
  },
  "allOf":[
    { "$ref": "#/definitions/foo" },
    { "$ref": "#/definitions/bar" }
  ]
}

with JSON Schema Lint, but I get an error 🛑

Field Error Value
.definitions['foo'].properties['a'] should be object,boolean "string"
.definitions['bar'].properties['b'] should be object,boolean "number"
@ferologics
Copy link
Author

ferologics commented Oct 16, 2020

Just to illustrate I thought maybe something like this would work but it's not a valid JSON:

"allOf":[
+  "enum": [
+   { "$ref": "#/definitions/foo" },
+   { "$ref": "#/definitions/bar" }
+  ]
]

@ferologics
Copy link
Author

ferologics commented Oct 16, 2020

Okay I got the schema:

{
  "definitions": {
    "foo" : { "a" : "string" },
    "bar" : { "b":"integer" }
  },
  "allOf":[
    { "$ref": "#/definitions/foo" }, 
    { "$ref": "#/definitions/bar" },
    {
      "properties" : {
        "type" : {
          "enum" : [
            "foo",
            "bar"
          ]
        }
      }
    }
  ]
}

and it validates to:

[
  { "type": "foo", "a": "string" },
  { "type": "bar", "b": 0 }
]

now I'm concerned with how to make it "schemasafe".
Right now even this is "valid":

[
  { "type": "bar", "a": "string" },
  { "type": "foo", "b": 0 }
]

How can I restrict foo to always have "a" : "string" and bar to have a "b":"integer"?

@ferologics
Copy link
Author

I tried to use the array type with items schema:

{
  "definitions":{
    "foo":{ "a":"string" },
    "bar":{ "b":"integer" }
  },
  "type":"array",
  "items":{
    "oneOf":[
      { "$ref":"#/definitions/foo" },
      { "$ref":"#/definitions/bar" }
    ]
  }
}

but this doesn't match my output

[
  {"type": "foo", "a":"" },
  {"type": "bar", "b":1 }  
]

and I get the error 🛑

Field Error Value
[0] should match exactly one schema in oneOf { "type": "foo", "a": "" }
[1] should match exactly one schema in oneOf { "type": "bar", "b": 1 }

@ferologics
Copy link
Author

ferologics commented Oct 16, 2020

This type of schema also does not work against the required JSON.

{
  "definitions":{
    "foo":{ "a":"string" },
    "bar":{ "b":"integer" }
  },
  "type":"array",
  "items":{
    "oneOf":[
      {
        "$ref":"#/definitions/foo", 
        "properties": { "type": { "enum": ["foo"] } }, "required": ["type"] 
      },
      { 
        "$ref":"#/definitions/bar", 
        "properties": { "type": { "enum": ["bar"] } }, "required": ["type"] 
      }
    ]
  }
}

How can I match the type requirement?

@ferologics
Copy link
Author

I think I've finally got the hang of it. This would be an example using the discriminator:

{
   "schemas": {
      "Baz": {
         "type": "object",
         "discriminator": {
            "propertyName": "type",
            "mapping": {
               "foo": "#/schemas/Foo",
               "bar": "#/schemas/Bar"
            }
         },
         "properties": {
            "type": {
               "description": "Type of an object",
               "type": "string"
            }
         }
      },
      "Foo": {
         "allOf": [
            {
               "$ref": "#schemas/Baz"
            },
            {
               "type": "object",
               "properties": {
                  "a": "string"
               },
               "required": [
                  "a"
               ]
            }
         ]
      },
      "Bar": {
         "allOf": [
            {
               "$ref": "#schemas/Baz"
            },
            {
               "type": "object",
               "properties": {
                  "b": "int"
               },
               "required": [
                  "b"
               ]
            }
         ]
      }
   }
}

However I'm feel like I'm still lacking the full understanding to produce an idiomatic formula for representing a heterogeneous collection of either Foo or Bar objects. There seems to be many ways of representing such a collection but I'd like it to be 'schemasafe'.

@ferologics
Copy link
Author

I've got an answer to the issue elsewhere.

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

1 participant