16

I started to use swagger with swagger-ui-express and swagger-jsdoc to auto document my existing API, which is written with nodejs and express (like described here - example).

I came across a problem when I tried to add a $ref to an existing JSON Schema file (that sits inside my project on the same directory as all my js files) on my annotation.

My directory looks like this

I tried to write the local path (./schema.json) and the absolute path, tried to use #, using many syntaxes and nothing worked.

My annotation looks like this:

/**
 * @swagger
 * /testing:
 *    get:
 *      description: This should show the json schema
 *      responses:
 *          200:
 *              description: "successful operation"
 *              schema:
 *                 $ref: "./schema.json"
 */

I expected the swagger ui to show me the JSON schema in my request section by. I get the following error -

Resolver error at paths./testing.get.responses.200.schema.$ref
Could not resolve reference: Tried to resolve a relative URL, without having a basePath. path: './schema.json' basePath: 'undefined'.

I looked the problem up online and couldn’t find any clear answer. I saw a solution that suggested I should put my schema on a server and access it with an URL address but I prefer not to do it on this point.

Also, at some point, I saved the scheme in a variable and then put it in the $ref and it worked fine. The only problem was that the scheme included some inner refs to an element in the same file and Swagger couldn't resolve them.

Is there a way to work properly with $ref in swagger-ui-express?

Yuri
  • 4,254
  • 1
  • 29
  • 46
Liza Talis
  • 181
  • 1
  • 1
  • 5
  • there ist an open ticket on github: https://github.com/arjun-g/vs-swagger-viewer/issues/45 – Joe Jan 17 '19 at 11:14
  • 1
    Sadly, issues concerning paths inside `$ref` plague nearly each Swagger/OpenAPI tool. Vote for fixing them or post a PR at Github. – Yuri Apr 02 '19 at 13:54

2 Answers2

3

Is there a way to work properly with $ref in swagger-ui-express?

Yes, there is, you have to resolve references in your YAML files by your self first, and provide result to Swagger UI then. You can do it with json-refs and yamljs libraries.

Here is the code snippet below shows you how you can do it:

const yamljs = require('yamljs');
const { resolveRefs } = require('json-refs');

/**
 * Return JSON with resolved references
 * @param {array | object} root - The structure to find JSON References within (Swagger spec)
 * @returns {Promise.<JSON>}
 */
const multiFileSwagger = (root) => {
  const options = {
    filter: ["relative", "remote"],
    loaderOptions: {
      processContent: function (res, callback) {
        callback(null, yamljs.parse(res.text));
      },
    },
  };

  return resolveRefs(root, options).then(
    function (results) {
      return results.resolved;
    },
    function (err) {
      console.log(err.stack);
    }
  );
};


const swaggerDocument = await multiFileSwagger(
  yamljs.load(path.resolve(__dirname, "./openapi/v1.yaml"))
);

You can also check the repo with full example how this solution works with swagger-ui-express: https://github.com/chuve/swagger-multi-file-spec

Marco Ottolini
  • 445
  • 2
  • 6
  • 15
chuve
  • 708
  • 7
  • 20
  • 2
    If you are executing this function not in the same path of the YAML file, consider to add `location: ` to the options. Ref: https://github.com/whitlockjc/json-refs/blob/master/docs/API.md#module_json-refs.JsonRefsOptions – Marco Ottolini Jan 04 '21 at 07:26
1

got the same problem here and find your question.

I've just solved mine so I guess I might help.

First, have you tried:

schema:
      $ref: "schema.json"

without the . This is how they teach at the documentation.