webapi-parser icon indicating copy to clipboard operation
webapi-parser copied to clipboard

Unresolved reference when converting from OAS 2.0 to RAML 1.0

Open benthurley82 opened this issue 5 years ago • 1 comments

I have been using this API to convert an API spec from OAS 2.0 to RAML 1.0 like so.

WebApiDocument doc = (WebApiDocument) Oas20.parse(oas20).get(); 
raml10 = Raml10.generateString(doc).get();

However, one of the types is not being converted correctly and attempting to use the RAML shows there are errors.

e.g. OAS 2.0

  "definitions": {
    "BaseResponse": {
      "type": "object",
      "properties": {
        "errors": {
          "type": "array",
          "xml": {
            "name": "errors",
            "attribute": false,
            "wrapped": false
          },
          "items": {
            "$ref": "#/definitions/LedgerEntry"
          }
        }
      },
      "title": "BaseResponse"
    },
...
    "LedgerEntry": {
      "type": "object",
      "properties": {
        "code": {
          "type": "string"
        },
        "description": {
          "type": "string"
        },
        "severity": {
          "type": "string",
          "enum": [
            "INFO",
            "WARN",
            "VALIDATION",
            "ERROR",
            "FATAL",
            "CONSTRAINT"
          ]
        }
      },
      "title": "LedgerEntry"
    },

Results in RAML 1.0

  LedgerEntry:
    displayName: LedgerEntry
    type: object
    properties:
      code:
        type: string
        required: false
      description:
        type: string
        required: false
      severity:
        enum:
          - INFO
          - WARN
          - VALIDATION
          - ERROR
          - FATAL
          - CONSTRAINT
        type: string
        required: false
...
  BaseResponse:
    displayName: BaseResponse
    type: object
    properties:
      errors:
        xml:
          attribute: false
          wrapped: false
          name: errors
        type: array
        items: "#/definitions/LedgerEntry"
        required: false

Using the API designer in the Anypoint Design Centre I was able to correct the above RAML to the following:

items: LedgerEntry

My expectation is that the RAML is generated without errors.

Thanks Ben

benthurley82 avatar Mar 05 '20 15:03 benthurley82

Hi @benthurley82.

Thanks for reporting this bug. It will be resolved when we update our dependency lib - AMF to 4.0.5. At the moment I can't give you ETA of when this will be done.

For now you can use an API called model resolution. It flattens the model/document but fixes this issues.

It may be performed in two ways, both of which have different pros and cons:

  1. Official way, like so which produces [1]
  2. Unofficial way, as in the code snippet below, which produces [2]:
import amf.client.model.document.Document;
import amf.client.resolve.Resolver;
...
WebApiDocument oasDoc = (WebApiDocument) Oas20.parse("somefile").get();

Resolver res = new Resolver("RAML 1.0");
Document resolvedDoc = (Document) res.resolve(oasDoc, "editing");
WebApiDocument wapDoc = new WebApiDocument();
wapDoc.withEncodes((WebApi) resolvedDoc.encodes());
wapDoc.withDeclares(resolvedDoc.declares());
// Copy other things from the model if necessary 

String ramlStr = Raml10.generateString(wapDoc).get();
System.out.println("Generated RAML string:\n" + ramlStr);

[0] Input OAS

{
  "swagger": "2.0",
  "info": {
    "title": "API with Types",
    "version": ""
  },
  "paths": {
    "/users": {
      "get": {
        "responses": {
          "200": {
            "schema": {
              "$ref": "#/definitions/BaseResponse"
            }
          }
        }
      }
    }
  },
  "definitions": {
    "BaseResponse": {
      "type": "object",
      "properties": {
        "errors": {
          "type": "array",
          "xml": {
            "name": "errors",
            "attribute": false,
            "wrapped": false
          },
          "items": {
            "$ref": "#/definitions/LedgerEntry"
          }
        }
      },
      "title": "BaseResponse"
    },
    "LedgerEntry": {
      "type": "object",
      "properties": {
        "code": {
          "type": "string"
        },
        "description": {
          "type": "string"
        },
        "severity": {
          "type": "string",
          "enum": [
            "INFO",
            "WARN",
            "VALIDATION",
            "ERROR",
            "FATAL",
            "CONSTRAINT"
          ]
        }
      },
      "title": "LedgerEntry"
    }
  }
}

[1]

#%RAML 1.0
title: API with Types
version: ""
/users:
  get:
    responses:
      "200":
        body:
          displayName: BaseResponse
          type: object
          additionalProperties: true
          properties:
            errors:
              xml:
                attribute: false
                wrapped: false
                name: errors
              type: array
              items:
                displayName: LedgerEntry
                type: object
                additionalProperties: true
                properties:
                  code:
                    type: string
                    required: false
                  description:
                    type: string
                    required: false
                  severity:
                    enum:
                      - INFO
                      - WARN
                      - VALIDATION
                      - ERROR
                      - FATAL
                      - CONSTRAINT
                    type: string
                    required: false
              required: false

[2]

#%RAML 1.0
types:
  BaseResponse:
    displayName: BaseResponse
    type: object
    additionalProperties: true
    properties:
      errors:
        xml:
          attribute: false
          wrapped: false
          name: errors
        type: array
        items:
          displayName: LedgerEntry
          type: object
          additionalProperties: true
          properties:
            code:
              type: string
              required: false
            description:
              type: string
              required: false
            severity:
              enum:
                - INFO
                - WARN
                - VALIDATION
                - ERROR
                - FATAL
                - CONSTRAINT
              type: string
              required: false
        required: false
  LedgerEntry:
    displayName: LedgerEntry
    type: object
    additionalProperties: true
    properties:
      code:
        type: string
        required: false
      description:
        type: string
        required: false
      severity:
        enum:
          - INFO
          - WARN
          - VALIDATION
          - ERROR
          - FATAL
          - CONSTRAINT
        type: string
        required: false
title: API with Types
version: ""
/users:
  get:
    responses:
      "200":
        body:
          displayName: BaseResponse
          type: object
          additionalProperties: true
          properties:
            errors:
              xml:
                attribute: false
                wrapped: false
                name: errors
              type: array
              items:
                displayName: LedgerEntry
                type: object
                additionalProperties: true
                properties:
                  code:
                    type: string
                    required: false
                  description:
                    type: string
                    required: false
                  severity:
                    enum:
                      - INFO
                      - WARN
                      - VALIDATION
                      - ERROR
                      - FATAL
                      - CONSTRAINT
                    type: string
                    required: false
              required: false

postatum avatar Mar 06 '20 10:03 postatum