Aleks
Aleks

Reputation: 5854

Embedded object in loopback model schema for Swagger

In the context of a remote method, I'm trying to define a model schema of a parameter passed in the body. This object looks like this:

{
    name: "Alex",
    credentials: {
        user: "alex",
        pass: "pass"
    }
}

So, I have this code in my remote method definition:

  MyModel.remoteMethod("postSomething", {
    accepts: [
      {arg: 'person', type: {
          "name": "string",
          "credentials": {
            "type": "object",
            "properties": {
              "user": "string",
              "pass: "string"
            }
          }
        }, http: {source: 'body'}, required: true
      }
    ],
.....

Unfortunatelly, the details of this embedded object (credentials) are not shown in the generated Swagger explorer. This is what I see:

{
    "user": "string",
    "credentials": {}
}

I've tried many different ways but I could not show the properties of the credentials object.

Any ideas?

Upvotes: 2

Views: 1692

Answers (2)

abhinav
abhinav

Reputation: 697

Loopback swagger only picks up the outer object ignoring the properties of the object. If you want to show a nested object in the swagger docs for the request body, you will have to make nested model.

Assuming you have a model called as person. You have to create another model named "credentials" having properties user and password. Then define the relationship in your person model's config

{
  "name": "Person",
  "base": "PersistedModel",
  "idInjection": true,
  "options": {
    "validateUpsert": true
  },
  "properties": {
    "name": {
      "type": "string",
      "required": true
    }
  },
  "validations": [],
  "relations": {
    "credentials": {
      "type": "embedsOne",
      "model": "credentials",
      "property": "credentials",
      "options": {
        "validate": true,
        "forceId": false
      }
    }
  },
  "acls": [],
  "methods": {}
}

And add a reference to this model where you define your remote method

MyModel.remoteMethod("postSomething", {
    accepts: [
      {arg: 'person', type: {Person}, 
       http: {source: 'body'}, required: true
      }
    ],

To avoid "Treating unknown remoting type" warning make sure your model is marked as "public" inside your "model-config.json"

Upvotes: 0

Zak Barbuto
Zak Barbuto

Reputation: 81

Loopback 2.x

Edit: Note the following only works for Loopback 2.x, as the type registry changed in 3.x.

The problem is that the data you are providing needs to be on the type property for the nested value. This should work:

MyModel.remoteMethod('postSomething', {
accepts: [
  {
    arg: 'person',
    type: {
      name: 'string',
      credentials: {
        type: {
          user: 'string',
          pass: 'string'
        }
      }
    },
    http: {
      source: 'body'
    },
    required: true
  }
],
//...

This also works with arrays:

 accepts: [
  {
    arg: 'Book',
    type: {
      title: 'string',
      author: 'string',
      pages: [{
        type: {
          pageNo: 'number',
          text: 'string'
        }
      }]
    }
  }
],
// ...

Loopback 3.x

Since the model registry and strong remoting changed in Loopback 3.x to only allow string or array types, you can't really avoid creating a new model. If you would like to quickly 'inline' a model without going through the full process of adding the model json file, adding it to model-config.json etc. you can register it directly on the app:

app.registry.createModel('Person', {
  firstName: 'string',
  lastName: 'string'
}, { base: 'Model' });

You can set the base to one of your other models if you want to extend an existing model (e.g, add another property that is only accepted in the given remote method)

If you want to create the model without cluttering up your model registry, you can do so by calling createModel on loobpack itself:

const loopback = require('loopback')
const modl = loopback.createModel({
    name: 'Person',
    base: null,
    properties: {
      firstName: {
        type: 'string',
        id: true // means it won't have an id property
      }
    }
  });

In both of the above examples, you refer to the model by name to attach it to the remote method:

accepts: [
  {
    arg: 'Person',
    type: 'Person'
  }
],
// ...

Note you will need to create a sub-model for every sub-property (e.g. credentials)

Upvotes: 4

Related Questions