Reputation: 174
I have many days reading a lot and doing several tests with this, without the expected results. I need validate an API response with its JSON schema (Swagger 2.0). The JSON is longer but I've reduced it to simply. I need to know if "code" and "message" keywords in the response have the type and values defined. Here the code I'm using:
var Ajv = require('ajv');
var ajv = new Ajv();
var schema = {
"host": "cert",
"paths": {
"products": {
"get": {
"responses": {
"401": {
"description": "Problem with the client request",
"headers": {
"x-correlator": {
"type": "string",
"format": "uuid",
"description": "Correlation id"
}
},
"schema": {
"$ref": "file:///../errors.json#/definitions/Unauthenticated"
}
}
}
}
},
"products": {
"get": {
"responses": {
"401": {
"description": "Problem with the client request",
"headers": {
"x-correlator": {
"type": "string",
"format": "uuid",
"description": "Correlation id"
}
},
"schema": {
"$ref": "file:///../errors.json#/definitions/Unauthenticated"
},
"examples": {
"application/json": {
"code": "UNAUTHENTICATED",
"message": "Authentication error"
}
}
}
}
}
}
}
}
var errors_schema = {
"info": {
"description": "Common errors",
"version": "3.0.1",
"title": "Common errors",
"contact": {
"name": "Team"
}
},
"definitions": {
"ModelError": {
"type": "object",
"required": [
"message"
],
"properties": {
"message": {
"type": "string",
"description": "A human readable description"
}
}
},
"Unauthenticated": {
"allOf": [
{
"type": "object",
"required": [
"code"
],
"properties": {
"code": {
"type": "string",
"enum": [
"UNAUTHENTICATED"
],
"default": "UNAUTHENTICATED",
"description": "Request not authenticated due to missing, invalid, or expired credentials."
}
}
},
{
"$ref": "#/definitions/ModelError"
}
]
}
}
}
ajv.addSchema(errors_schema, 'file:///../errors.json');
var testajv = ajv.compile(schema);
var response = {"code": 123, "message":"token expired"}
var valid = testajv(response);
console.log(valid);
if(!valid) {
console.log(testajv.errors);
}
As you see the keyword "code" in the response is '123' integer but in the schema it is defined as string. Independently of the value the validation always gets 'true'. What should I do to get my needs? Thanks in advance.
Upvotes: 1
Views: 5901
Reputation: 4062
Swagger schema contains multiple JSON schemas organized in API structure, you need to address a correct part of Swagger schema to employ JSON schema for validation.
Please check example code (https://runkit.com/embed/bwj42juwyjo4):
var Ajv = require('ajv');
var ajv = new Ajv();
var schema = {
"host": "cert",
"paths": {
"products": {
"get": {
"responses": {
"401": {
"description": "Problem with the client request",
"headers": {
"x-correlator": {
"type": "string",
"format": "uuid",
"description": "Correlation id"
}
},
"schema": {
"$ref": "errors.json#/definitions/Unauthenticated"
}
}
}
}
},
"products": {
"get": {
"responses": {
"401": {
"description": "Problem with the client request",
"headers": {
"x-correlator": {
"type": "string",
"format": "uuid",
"description": "Correlation id"
}
},
"schema": {
"$ref": "errors.json#/definitions/Unauthenticated"
},
"examples": {
"application/json": {
"code": "UNAUTHENTICATED",
"message": "Authentication error"
}
}
}
}
}
}
}
}
var errors_schema = {
"info": {
"description": "Common errors",
"version": "3.0.1",
"title": "Common errors",
"contact": {
"name": "Team"
}
},
"definitions": {
"ModelError": {
"type": "object",
"required": [
"message"
],
"properties": {
"message": {
"type": "string",
"description": "A human readable description"
}
}
},
"Unauthenticated": {
"allOf": [
{
"type": "object",
"required": [
"code"
],
"properties": {
"code": {
"type": "string",
"enum": [
"UNAUTHENTICATED"
],
"default": "UNAUTHENTICATED",
"description": "Request not authenticated due to missing, invalid, or expired credentials."
}
}
},
{
"$ref": "#/definitions/ModelError"
}
]
}
}
}
ajv.addSchema(errors_schema, 'errors.json');
ajv.addSchema(schema, 'swagger.json')
var testajv = ajv.compile({ $ref: 'errors.json#/definitions/Unauthenticated' });
console.log(testajv({"code": 123, "message":"token expired"}), testajv.errors); // Fails
console.log(testajv({"code": "AAA", "message":"token expired"}), testajv.errors); // Fails
console.log(testajv({"code": "UNAUTHENTICATED", "message":"token expired"}), testajv.errors); // Passes
var testajv2 = ajv.compile({ $ref: 'swagger.json#/paths/products/get/responses/401/schema' });
console.log(testajv2({"code": 123, "message":"token expired"}), testajv2.errors); // Fails
console.log(testajv2({"code": "AAA", "message":"token expired"}), testajv2.errors); // Fails
console.log(testajv2({"code": "UNAUTHENTICATED", "message":"token expired"}), testajv2.errors); // Passes
Some more information in relevant ajv
issue: https://github.com/epoberezkin/ajv/issues/195
Upvotes: 1
Reputation: 148
Use type as number instead of string in code property.
"properties": {
"code": {
"type": "number",
"enum": [
"UNAUTHENTICATED"
],
"default": "UNAUTHENTICATED",
"description": "Request not authenticated due to missing, invalid, or expired credentials."
}
}
Upvotes: 0