Sebastian Diaz
Sebastian Diaz

Reputation: 174

Wrong output during API validation response against JSON schema using AJV

I'm using AJV to validate an API response against JSON schema (swagger). This is the script to do the validation:

var Ajv = require('ajv');
var ajv = new Ajv();

var schema = {
    "paths": {
      "/users": {
        "get": {
          "security": [
            {
              "3_legged": [
                "userprofile-search"
              ]
            }
          ],
          "parameters": [
            {
              "$ref": "#/parameters/IdentitiesId"
            },
            {
              "$ref": "#/parameters/IdDocumentValue"
            },
            {
              "$ref": "#/parameters/IdDocumentType"
            }
          ],          
          "responses": {
            "200": {
              "headers": {
                "x-correlator": {
                  "type": "string",
                  "format": "uuid",
                }
              },
              "schema": {
                "type": "array",
                "items": {
                  "$ref": "#/definitions/UserProfile"
                }
              }
            }
          }
        }
      },
      "/users/{user_id}": {
        "get": {
          "security": [
            {
              "3_legged": [
                "userprofile-read"
              ]
            }
          ],
          "tags": [
            "users"
          ],
          "operationId": "getUserProfileInfo",
          "parameters": [
            {
              "$ref": "#/parameters/UserId"
            }
          ],          
          "responses": {
            "200": {
              "description": "OK",
              "headers": {
                "x-correlator": {
                  "type": "string",
                  "format": "uuid",
                  "description": "Correlation id"
                }
              },
              "schema": {
                "$ref": "#/definitions/UserProfile"
              },
              "examples": {
                "application/json": {
                  "id": "A000-0000-0001",
                  "name": "Andrés Iniesta",
                  "id_document": {
                    "country": "ES",
                    "type": "NIF",
                    "value": "value"
                  },
                  "identities": [
                    {
                      "type": "email",
                      "id": "id",
                      "services": [
                        "iptv",
                        "email"
                      ]
                    },
                    {
                      "type": "phone_number",
                      "id": "id",
                      "services": [
                        "mobile"
                      ]
                    },
                    {
                      "type": "phone_number",
                      "id": "id",
                      "services": [
                        "mobile"
                      ]
                    },
                    {
                      "type": "phone_number",
                      "id": "id",
                      "services": [
                        "landline",
                        "broadband"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
  "definitions": {
    "UserProfile": {
      "type": "object",
      "required": [
        "id",
        "name",
        "identities"
      ],
      "properties": {
        "id": {
          "type": "string"
        },
        "name": {
          "type": "string"
        },
        "id_document": {
          "$ref": "common.json#/definitions/IdDocument"
        },
        "identities": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/Identity"
          }
        }
      }
    },
    "Identity": {
      "type": "object",
      "required": [
        "id",
        "services",
        "type"
      ],
      "properties": {
        "type": {
          "type": "string",
          "enum": [
            "phone_number",
            "email",
            "uid"
          ]
        },
        "services": {
          "type": "array",
          "items": {
            "type": "string",
            "enum": [
              "mobile",
              "invoicing"
            ]
          }
        },
        "id": {
          "type": "string"
        }
      }
    }
  }
}

var common = {
  "definitions": {
    "MoneyAmount": {
      "type": "object",
      "properties": {
        "amount": {
          "type": "number"
        }
      }
    },
    "IdDocument": {
      "type": "object",
      "required": [
        "country",
        "type",
        "value"
      ],
      "properties": {
        "country": {
          "type": "string"
        },
        "type": {
          "type": "string"
        },
        "value": {
          "type": "string"
        }
      }
    }
  }
}

var response={
    "id": "123456789",
    "name": "pruebas trocafone prepago",
    "id_document": {
        "country": "ARG",
        "type": "P",
        "value": "15042016"
    },
    "identities": [
        {
            "type": "uid",
            "services": [
                "invoicing"
            ],
            "id": "511644813"
        },
        {
            "type": "phone_number",
            "services": [
                "mobile"
            ],
            "id": "00123456789"
        },
        {
            "type": "email",
            "services": [
                "email"
            ],
            "id": ""
        }
    ]
}

ajv.addSchema(schema, 'user_profile.json');
ajv.addSchema(common, 'common.json');

var testajv = ajv.compile({ $ref: 'common.json#/definitions/IdDocument' });

console.log(testajv(JSON.stringify(response)), testajv.errors);

Then, I get this output:

schema id ignored A000-0000-0001
false [ { keyword: 'type',
    dataPath: '',
    schemaPath: 'common.json#/definitions/IdDocument/type',
    params: { type: 'object' },
    message: 'should be object' } ]

1- I don't understand why ajv tell me that the "schema id" is ignored. Why does it important?

2- Why does it tell me that IdDocument/type "should be object"? It is object in the response, defined as follow:

"id_document": {
    "country": "ARG",
    "type": "P",
    "value": "15042016"
}

Could someone help me to understand it? Thanks in advance!

Upvotes: 2

Views: 1055

Answers (1)

vearutop
vearutop

Reputation: 4072

Swagger Schema is NOT a JSON Schema, therefore you have to address a correct place in Swagger Schema (schema.definitions.UserProfile).

Though Swagger Definition is not 100% compatible with JSON Schema, in most of cases you can use generic validator.

More info: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#schemaObject.

You need to remove JSON.stringify, as it creates a string from your data (string is not an object).

ajv.addSchema(schema.definitions.UserProfile, 'user_profile.json');
ajv.addSchema(common, 'common.json');

var testajv = ajv.compile({ $ref: 'common.json#/definitions/IdDocument' });

console.log(testajv(response), ajv.errorsText(testajv.errors));

https://runkit.com/embed/kn4gp1fs8vat

Upvotes: 2

Related Questions