raml-js-parser-2 icon indicating copy to clipboard operation
raml-js-parser-2 copied to clipboard

Consistency on array type interpretation

Open pimpreneil opened this issue 8 years ago • 5 comments

Today I stumbled on an issue on array type parsing. While using the raml2html lib that depends on the parser as well as the datatype-expansion, I have discovered that the [] syntax and the array/items notation don't produce the same output out of the parser.

Let's take this RAML:

#%RAML 1.0
title: Nesting bug
version: v1
baseUri: http://www.bug.com
types:
  Book:
    type: object
    properties:
      id: integer
  Library:
    type: object
    properties:
      id: integer
      books:
        type: array
        items: Book

/bug:
  get:
    responses:
      200:
        body:
          application/json:
            type: object
            properties:
              libraries:
                type: array
                items: Library

It will produce the following Library type after going through the parser:

"Library": {
  "name": "Library",
  "displayName": "Library",
  "typePropertyKind": "TYPE_EXPRESSION",
  "type": [
    "object"
  ],
  "properties": {
    "id": {},
    "books": {
      "name": "books",
      "displayName": "books",
      "typePropertyKind": "TYPE_EXPRESSION",
      "type": [
        "array"
      ],
      "required": true,
      "items": [
        "Book"
      ]
    }
  },
}

But if I use the [] notation, with the following RAML:

#%RAML 1.0
title: Nesting bug
version: v1
baseUri: http://www.bug.com
types:
  Book:
    type: object
    properties:
      id: integer
  Library:
    type: object
    properties:
      id: integer
      books:
        type: Book[]

/bug:
  get:
    responses:
      200:
        body:
          application/json:
            type: object
            properties:
              libraries:
                type: Library[]

I get the following Library type:

"Library": {
  "name": "Library",
  "displayName": "Library",
  "typePropertyKind": "TYPE_EXPRESSION",
  "type": [
    "object"
  ],
  "properties": {
    "id": {},
    "books": {
      "name": "books",
      "displayName": "books",
      "typePropertyKind": "TYPE_EXPRESSION",
      "type": [
        "array"
      ],
      "required": true,
      "items": "Book"
    }
  },
}

The difference is that in one case, the items field is an array and in the other, it is a string.

I wouldn't bother having two different syntax, but the issue is that the datatype-expansion's canonicalForm method doesn't support the array notation:

"books": {
    "name": "books",
    "displayName": "books",
    "typePropertyKind": "TYPE_EXPRESSION",
    "type": [
        "array"
    ],
    "required": true,
    "items": [
        "Book"
    ]
}

becomes that:

"books": {
    "type": "array",
    "displayName": "books",
    "name": "books",
    "typePropertyKind": "TYPE_EXPRESSION",
    "required": true,
    "items": {
        "type": "any"
    }
}

Whereas this (obtained when using the [] syntax):

"books": {
    "name": "books",
    "displayName": "books",
    "typePropertyKind": "TYPE_EXPRESSION",
    "type": [
        "array"
    ],
    "required": true,
    "items": "Book"
}

Becomes that (which is the expected result):

"books": {
    "type": "array",
    "displayName": "books",
    "name": "books",
    "typePropertyKind": "TYPE_EXPRESSION",
    "required": true,
    "items": {
        "type": "object",
        "properties": {
            "id": {
                "displayName": "id",
                "type": "integer",
                "required": true
            }
        },
        "additionalProperties": true,
        "displayName": "Book"
    }
}

pimpreneil avatar May 10 '17 13:05 pimpreneil

Not sure that I completely missed something but both outputs you posted have items with a string value.

sichvoge avatar May 10 '17 13:05 sichvoge

Right, bad copy paste ;)

pimpreneil avatar May 10 '17 13:05 pimpreneil

OK if that's the case, I actually think that items should be an object and not a string or array. For example, what happens if you define your items to be a type declaration?

So my suggestion is that the outcome should be:

"Library": {
  "name": "Library",
  "displayName": "Library",
  "typePropertyKind": "TYPE_EXPRESSION",
  "type": [
    "object"
  ],
  "properties": {
    "id": {},
    "books": {
      "name": "books",
      "displayName": "books",
      "typePropertyKind": "TYPE_EXPRESSION",
      "type": [
        "array"
      ],
      "required": true,
      "items": {
        "type": "Book"
      }
    }
  }
}

sichvoge avatar May 10 '17 13:05 sichvoge

And in the newer improved schema, that you get calling load, you actually see it is defined as oneOf (here).

@ddenisenko we should avoid using oneOf as much as possible. Do you see any cases where we need it? In this case (items), I currently don't see any as everything can be described as an object (type declaration) again (see this option here).

sichvoge avatar May 10 '17 14:05 sichvoge

Note that raml-js-parser-2 has been deprecated, the new official parser is webapi-parser. Feel free to attempt to reproduce this issue with webapi-parser and report any issue you may have on that repository.

postatum avatar Sep 25 '19 09:09 postatum