apiaryio / drafter

API Blueprint Parser (C++)
https://apiblueprint.org/
MIT License
301 stars 54 forks source link

Distinct OneOf gets parsed as single OneOf group in schema #785

Closed jqian33 closed 4 years ago

jqian33 commented 4 years ago

apib:

## X
- One Of
    - foo(number)
    - foo (boolean)
- One Of
    - bar (number)
    - bar (boolean)

json schema:

{
   "oneOf":[
      {
         "properties":{
            "foo":{
               "type":[
                  "number"
               ]
            }
         }
      },
      {
         "properties":{
            "foo":{
               "type":[
                  "boolean"
               ]
            }
         }
      },
      {
         "properties":{
            "bar":{
               "type":[
                  "number"
               ]
            }
         }
      },
      {
         "properties":{
            "bar":{
               "type":[
                  "boolean"
               ]
            }
         }
      }
   ]
}

I am expecting the two One Of statements to be in distinct groups:

{
   "oneOf":[
      {
         "properties":{
            "foo":{
               "type":[
                  "number"
               ]
            }
         }
      },
      {
         "properties":{
            "foo":{
               "type":[
                  "boolean"
               ]
            }
         }
      }
   ],
   "oneOf":[
      {
         "properties":{
            "bar":{
               "type":[
                  "number"
               ]
            }
         }
      },
      {
         "properties":{
            "bar":{
               "type":[
                  "boolean"
               ]
            }
         }
      }
   ]
}

Is there a different mson syntax i should use to achieve the expected schema or is this a bug?

kylef commented 4 years ago

Can you try and explain the type of structure you are trying to describe, and then I can attempt to advise on MSON used to describe it. It's not entirely clear to me on your intent from the One Of example.

Note your expected JSON Schema contains two oneOf keys in the same object, JSON keys are expected to be unique.

jqian33 commented 4 years ago

Both properties foo and bar can be either a number of boolean.

kylef commented 4 years ago

I'd suggest using enum to declare and exclusive list of types for each property. The following MSON will describe an object which may contain properties (foo and bar) which must be either a string or number:

+ foo (enum[string, number])
+ bar (enum[string, number])

You can extract the enum as a type, if desired:

## Data Structures

## MyObject

+ foo (StringOrNumber)
+ bar (StringOrNumber)

### StringOrNumber (enum[string, number])

These will product the following JSON Schema in Drafter 5:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "foo": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "number"
        }
      ]
    },
    "bar": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "number"
        }
      ]
    }
  }
}

If you want to descibe that they both need to be a number, or both need to be a string, then the following MSON will describe that as follows:

+ One Of
    + Properties
        + foo (number)
        + bar (number)
    + Properties
        + foo (string)
        + bar (string)

Which currently produces the following JSON Schema:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "allOf": [
    {
      "oneOf": [
        {
          "properties": {
            "foo": {
              "type": "number"
            },
            "bar": {
              "type": "number"
            }
          }
        },
        {
          "properties": {
            "foo": {
              "type": "string"
            },
            "bar": {
              "type": "string"
            }
          }
        }
      ]
    }
  ]
}
kylef commented 4 years ago

Please sustitute string for boolean in my above examples, I misread.

jqian33 commented 4 years ago

@kylef, thank you for providing the examples! This has solved my problem.