Unresolved reference when converting from OAS 2.0 to RAML 1.0
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
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:
- Official way, like so which produces [1]
- 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