I need to validate following response against JSON schema. The problem is it's always failing even if schema is valid.
{
"items": [
{
"uuid": "f68ad4ba-a11e-485d-a2d7-17b9b07bd8d3",
"name": "Code",
"type": "app_code",
"description": "Code 1",
"content_type": "application/javascript",
"audit": {
"created_date": "2017-11-02T00:16:58.000Z",
"created_by": "e7c97dc1-08eb-45ef-b883-d100553bac5c"
}
},
{
"uuid": "3c9e59b0-f6c7-4788-8a14-0b3e99fc4306",
"name": "Object demo 2",
"type": "app_code",
"description": "Object demo 2 description",
"content_type": "application/javascript",
"audit": {
"created_date": "2017-11-02T13:48:22.000Z",
"created_by": "e7c97dc1-08eb-45ef-b883-d100553bac5c"
}
},
{
"uuid": "e2f54e6c-a158-4f43-a332-1c99bb76684e",
"name": "toolbox_test_results",
"type": "toolbox_tests",
"description": "This is snapshots for React-OSS Toolbox",
"content_type": "application/json",
"audit": {
"created_date": "2017-11-07T11:29:02.000Z",
"created_by": "e7c97dc1-08eb-45ef-b883-d100553bac5c"
}
}
],
"metadata": {
"total": 124,
"count": 3
},
"links": [
{
"rel": "self",
"href": "http://microsvcs.star2star.net:10010/users/e7c97dc1-08eb-45ef-b883-d100553bac5c/objects?load_content=false&limit=3&offset=0"
},
{
"rel": "first",
"href": "http://microsvcs.star2star.net:10010/users/e7c97dc1-08eb-45ef-b883-d100553bac5c/objects?load_content=false&limit=3&offset=0"
},
{
"rel": "next",
"href": "http://microsvcs.star2star.net:10010/users/e7c97dc1-08eb-45ef-b883-d100553bac5c/objects?load_content=false&limit=3&offset=3"
},
{
"rel": "last",
"href": "http://microsvcs.star2star.net:10010/users/e7c97dc1-08eb-45ef-b883-d100553bac5c/objects?load_content=false&limit=3&offset=123"
}
]
}
I use following code for validation in Postman:
// Define the JSON Schema
const objectSchema = {
"items": [
{
"audit": {
"created_by": "string",
"created_date": "string",
"updated_by": "string",
"updated_date": "string"
},
"content": {},
"content_type": "string",
"description": "string",
"name": "string",
"type": "string",
"uuid": "string"
}
],
"links": [
{
"href": "string",
"rel": "string",
"templated": true
}
],
"metadata": {}
};
pm.test("JSON schema validation", function() {
var responseData = JSON.parse(responseBody);
var result = tv4.validate(responseData, objectSchema, false, true);
if (result !== true) {
console.log('Schema validation failed:', tv4.error);
}
pm.expect(result).to.be.true;
console.log(JSON.stringify(result));
});
How it's possible to get the detailed error in console (for example: which field has wrong type or missing)? Actual error from console:
message:"Unknown property (not in schema)"
name:"ValidationError"
type:"Error
"
Thank you in advance for answers!
Elaborating on #Pavlo's comment:
In your test:
pm.test("JSON schema validation", function() {
var responseData = JSON.parse(responseBody);
var result = tv4.validate(responseData, objectSchema, false, true);
if (result !== true) {
console.log('Schema validation failed:', tv4.error);
}
pm.expect(result).to.be.true;
console.log(JSON.stringify(result));
});
the line var responseData = JSON.parse(responseBody); should be replaced with:
var responseData = pm.response.json();
Also, from this answer you can add the following line to get more information about where the schema failed:
console.log(tv4.error.dataPath);
Related
I'll try to provide as much information as I think might be relevant. I'm using NodeJS, MongoDB, .rest, and Render, though in this case I'm just trying to get things working locally first. Here are some of the files.
//swagger.js
const swaggerAutogen = require('swagger-autogen')();
const doc = {
info: {
title: 'My API',
description: 'Welcome to my fumbling mess',
},
host: 'localhost:3000',
schemes: ['http'],
};
const outputFile = './swagger-output.json';
const endpointsFiles = ['routes/index.js'];
swaggerAutogen(outputFile, endpointsFiles, doc);
//routes/index.js
const routes = require('express').Router();
routes.use('/characters', require('./characters'));
routes.use('/', require('./swagger-route'));
module.exports = routes;
//routes/swagger-route.js
const router = require('express').Router();
const swaggerUi = require('swagger-ui-express');
const swaggerDocument = require('../swagger-output.json');
router.use('/api-docs', swaggerUi.serve);
router.use('/api-docs', swaggerUi.setup(swaggerDocument));
module.exports = router;
//swagger.output.json
{
"swagger": "2.0",
"info": {
"title": "My API",
"description": "Welcome to my fumbling mess",
"version": "1.0.0"
},
"host": "localhost:3000",
"basePath": "/",
"schemes": [
"http"
],
"paths": {
"/characters/": {
"get": {
"description": "",
"produces": [
"application/json"
],
"parameters": [],
"responses": {
"200": {
"description": "OK"
},
"500": {
"description": "Internal Server Error"
}
}
},
"post": {
"description": "",
"parameters": [
{
"name": "body",
"in": "body",
"schema": {
"type": "object",
"properties": {
"characterName": {
"example": "any"
},
"playerName": {
"example": "any"
},
"race": {
"example": "any"
},
"class": {
"example": "any"
},
"level": {
"example": "any"
},
"alignment": {
"example": "any"
},
"stats": {
"example": "any"
}
}
}
}
],
"responses": {
"201": {
"description": "Created"
},
"400": {
"description": "Bad Request"
}
}
}
},
"/characters/{id}": {
"get": {
"description": "",
"produces": [
"application/json"
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"type": "string"
}
],
"responses": {
"200": {
"description": "OK"
},
"500": {
"description": "Internal Server Error"
}
}
},
"put": {
"description": "",
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"type": "string"
},
{
"name": "body",
"in": "body",
"schema": {
"type": "object",
"properties": {
"characterName": {
"example": "any"
},
"playerName": {
"example": "any"
},
"race": {
"example": "any"
},
"class": {
"example": "any"
},
"level": {
"example": "any"
},
"alignment": {
"example": "any"
},
"stats": {
"example": "any"
}
}
}
}
],
"responses": {
"204": {
"description": "No Content"
},
"404": {
"description": "Not Found"
},
"500": {
"description": "Internal Server Error"
}
}
},
"delete": {
"description": "",
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"type": "string"
}
],
"responses": {
"200": {
"description": "OK"
},
"404": {
"description": "Not Found"
},
"500": {
"description": "Internal Server Error"
}
}
}
}
}
}
And finally, running http://localhost:3000/api-docs/ doesn't result in the actual frontend of the Swagger UI like it should. Instead I get this is raw html in the attached image.
Any ideas of what I could be doing wrong?
I tried in swagger-route.js to change the 5th line from router.get() to router.use()
I tried forgetting about localhost and changing the host paths to my Render web service but that just caused the same thing to happen on Render.
I want to automate my unit test cases using POSTMAN Collections API & NEWMAN.
I have created two test cases, which is working as expected. After exporting the collection from POSTMAN, I am generating the test report via NEWMAN.
But there some API which have some dependency on another, means need to pass one unique ID in parameter, which is coming from another API call. So how can I pass those parameter value in JSON.
Want to pass costID in my second API call/second test case.
{
"variables": [],
"info": {
"name": "UNIT TEST",
"_postman_id": "e518f4c6-8cd0-2484-aff3-2f2b288f938e",
"description": "",
"schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json"
},
"item": [
{
"name": "Price Testing",
"description": "",
"item": [
{
"name": "PDP",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"var jsonData = JSON.parse(responseBody);",
"var keyexist = \"YES\";",
"var key = \"**costID**\" in jsonData ? \"YES\" : \"NO\";",
"tests[\"costIDEXIST\"] = key === keyexist;"
""
]
}
}
],
"request": {
"url": {
raw": "my api url1",
"protocol": "https",
"host": [
"www",
"test",
"com"
],
"path": [
"jio",
"v4",
"l232"
],
"query": [
{
"key": "ispwa",
"value": "true",
"equals": true,
"description": ""
}
],
"variable": []
},
"method": "GET",
"header": [],
"body": {},
"description": ""
},
"response": []
}
]
},
{
"name": "TEST KEY CHECK",
"description": "",
"item": [
{
"name": "kEY EXIST OR NOT",
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"var jsonData = JSON.parse(responseBody);",
"var keyexist = \"YES\";",
"var key = \"ishEligible\" in jsonData ? \"YES\" : \"NO\";",
"tests[\"ishEligible EXIST\"] = key === keyexist;"
]
}
}
],
"request": {
"url": {
"raw": "my api url2",
"host": [
"TEST",
"com"
],
"path": [
"jio",
"v4",
"l232"
],
"query": [
{
"key": "**costID**",
"value": "true",
"equals": true,
"description": ""
}
],
"variable": []
},
"method": "GET",
"header": [],
"body": {},
"description": ""
},
"response": []
}
]
}
]
}
Yes, I got one solution by setting the costID in EnvironmentVariable. So that I can use that costID in subsequent API calls.
postman.setEnvironmentVariable(\"costID \",jsonData.costID);
use pm.collectionVariables.set("variable_key","variable_value");
instead of
pm.environment.set("variable_key", "variable_value");
I've got a JSON Schema that looks like this:
{
"required": [
"instructions"
],
"properties": {
"instructions": {
"title": "Instructions",
"minItems": 3,
"type": "array",
"items": {
"required": [
"typeId",
"teamId",
"disciplineId"
],
"properties": {
"typeId": {
"minimum": 1,
"title": "Appointment Type",
"type": "integer"
},
"teamId": {
"minimum": 1,
"title": "Team",
"type": "integer"
},
"disciplineId": {
"minimum": 1,
"title": "Discipline",
"type": "integer"
},
"prefClinicianId": {
"title": "Pref. Clinician",
"anyOf": [
{
"type": "null"
},
{
"minimum": 1,
"type": "integer"
}
]
},
"prefTime": {
"title": "Pref. Time",
"anyOf": [
{
"type": "null"
},
{
"type": "integer"
}
]
},
"childRequired": {
"title": "Child Req'd",
"type": "boolean"
}
},
"type": "object"
}
}
},
"type": "object"
}
As you can see, I've added titles to all the properties. However, the error object I get back looks like:
[
{
"keyword": "minItems",
"dataPath": ".instructions",
"schemaPath": "#/properties/instructions/minItems",
"params": {
"limit": 3
},
"message": "should NOT have less than 3 items"
},
{
"keyword": "type",
"dataPath": ".instructions[0].typeId",
"schemaPath": "#/properties/instructions/items/properties/typeId/type",
"params": {
"type": "integer"
},
"message": "should be integer"
},
{
"keyword": "type",
"dataPath": ".instructions[0].teamId",
"schemaPath": "#/properties/instructions/items/properties/teamId/type",
"params": {
"type": "integer"
},
"message": "should be integer"
},
{
"keyword": "type",
"dataPath": ".instructions[0].disciplineId",
"schemaPath": "#/properties/instructions/items/properties/disciplineId/type",
"params": {
"type": "integer"
},
"message": "should be integer"
}
]
As you can see, the title is not in there. How can I get the titles with the errors?
Please note that this question is specific to AJV.
When you create your AJV object set the verbose option to true.
This will add a parentSchema property to the ajv error with the original schema. It will also add a schema property that contains the specific schema attribute that caused the validation failure.
Here's an example:
var ajv = new Ajv({
$data: true,
verbose: true
});
let schema = {
title: 'object title',
type: 'object',
properties: {
str: {
title: "A string property",
type: "string"
}
}
};
let data = {
str: 3
};
ajv.validate(schema, data)
console.log('ERRORS: ', this.ajv.errors)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ajv/5.3.0/ajv.bundle.js"></script>
I don't know if I'm just blind or something but how can I do the following:
I have a User model with a hasOne relation to a UserData model. I only want one property of UserData directly in the results of User.
The relation in User looks like this:
"relations": {
"userData": {
"type": "hasOne",
"model": "UserData"
}
}
And the default scope in User:
"scope": {
"include": "userData"
}
So the result for one User is:
[
{
"id": 5,
"email": "example#example.com",
"name": "Example",
"userData": {
"id": 5,
"birthdate": "1971-09-06T00:00:00.000Z"
}
}
]
But what I want is this:
[
{
"id": 5,
"email": "example#example.com",
"name": "Example",
"birthdate": "1971-09-06T00:00:00.000Z"
}
]
How can I achive this?
Edit:
The two model definitions:
ChiliUser:
{
"name": "ChiliUser",
"base": "ChiliUserData",
"idInjection": true,
"options": {
"validateUpsert": true,
"mysql": {
"table": "person"
}
},
"properties": {
"id": {
"type": "number"
},
"email": {
"type": "string"
},
"password": {
"type": "string"
},
"vorname": {
"type": "string"
},
"name": {
"type": "string"
},
"spitzname": {
"type": "string"
},
"strasse": {
"type": "string"
},
"plz": {
"type": "number"
},
"ort": {
"type": "string"
},
"geolat": {
"type": "string"
},
"geolng": {
"type": "string"
}
},
"validations": [],
"relations": {},
"acls": [],
"methods": []
}
ChiliUserData:
{
"name": "ChiliUserData",
"base": "PersistedModel",
"idInjection": true,
"options": {
"validateUpsert": true,
"mysql": {
"table": "person_data"
}
},
"properties": {
"id": {
"type": "number"
},
"person_id": {
"type": "number"
},
"birthdate": {
"type": "date"
}
},
"validations": [],
"relations": {},
"acls": [],
"methods": []
}
Are you using the built-in User model? If you are, you can simply extend it with your UserData model using base: "User", and the underlying schema will be as you desire:
{
"name": "UserData",
"base": "User",
"properties": {}
...
}
But this setup would mean you'd use UserData over User in your code. Since the built-in User model gets in the way, I'd recommend a different word like Person or Customer, in which case it would look like:
{
"name": "Person",
"base": "User",
"properties": {
...extra user data properties only...
}
...
}
This way, only Person will have all the extra "user data" fields on it, but will also include all the fields/methods defined for User inside node_modules/loopback/common/models/User.json. If you're using MySQL, the Person table will be created with the combination of fields from both User and Person.
i have used $.getJSON for getting json data on pagebeforeshow but it is not working as it have to.
$(document).on('pagebeforeshow', '#inpGrid', function(e) {
alert("inpGrid");
var tat_url = "http://192.168./html5/Demo/json/list.json";
var url = "http://api.openweathermap.org/data/2.5/forecast?lat=35&lon=139&callback=?" ;
$.getJSON(tat_url, function(res) {
console.log(res)
});
});
the code is as above, when using url in $.getJSON it is working, wheras as using tat_url it is not working.
the http://192.168./html5/Demo/json/list.json consists as follows
{
"response": {
"respCode": 0,
"output": {
"delAction": "OP",
"delTmplt": "sibcVizEdit",
"title": "List TATs",
"layout": "grid",
"srvObjRef": "iawme1/IAWMblztnExpert-ListSIBCs_MB1412577249595",
"startIndex": "0",
"recsPerPage": "18",
"noPages": "1",
"curPageNo": "1",
"fieldInfo": [
{
"label": "Name",
"type": "STRING"
}
{
"label": "Alias",
"type": "STRING"
}
{
"label": "Datatype",
"type": "STRING"
}
{
"label": "Default Value",
"type": "STRING"
}
{
"label": "Visibility",
"type": "STRING"
}
],
"records": [
{
"Name": "psngrType"
"Alias": "Pasngr Type"
"Datatype": "STRING"
"Default Value":"CC"
"Visibility": "0"
},
{
"Name": "flightNo"
"Alias": "Flight No"
"Datatype": "STRING"
"Default Value":"$RV_flightNo"
"Visibility": "0"
}
],
"relServices": {
"AServices": [
{
"ref": "IAWMblztnExpert-ListSIBCs-UpdateBizContext_MB",
"title": "Update SIBC",
"desc": "",
"srvRef": "IAWMblztnExpert-ListSIBCs-UpdateBizContext_MB",
"slctdOffsets": "0"
},
{
"ref": "IAWMblztnExpert-ListSIBCs-ListIICsInSIBC_MB",
"title": "List IICs",
"desc": "",
"srvRef": "IAWMblztnExpert-ListSIBCs-ListIICsInSIBC_MB",
"slctdOffsets": "0"
},
{
"ref": "IAWMblztnExpert-ListSIBCs-Deploy SIBC_MB",
"title": "Deploy",
"desc": "",
"srvRef": "IAWMblztnExpert-ListSIBCs-Deploy SIBC_MB",
"slctdOffsets": "0"
}
]
}
}
}
}
Can someone help me please thanks.
Your JSON contain syntax errors, look your ''fieldInfo'' node. You didn't seperate your differents object by ,
Example:
{
"label": "Name",
"type": "STRING"
},
{
"label": "Alias",
"type": "STRING"
}
instead of
{
"label": "Name",
"type": "STRING"
}
{
"label": "Alias",
"type": "STRING"
}
Use online JSON validator if you need check rest of your json file easily : http://jsonlint.com/