I am facing problem regarding AJV Schema Validator.
I have following schema
{
"$id": "create-offer.json#",
"body": {
"type": "object",
"properties": {
"statusCode": {
"type": "number"
},
"id": {
"type": "string"
},
"name": {
"type": "string"
},
"description": {
"type": "string"
},
"status": {
"type": "string"
},
"type": {
"type": "string"
},
"routePlanId": {
"type": "string"
},
"currencyId": {
"type": "string"
},
"autoRateUpdateActive": {
"type": "boolean"
}
}
}
}
And my response is :
{ statusCode: 2006,
statusPhrase: 'Error: ORA-00001: unique constraint (SPHERE_D1.CHECK_UNIQUE_RATE_NAME) violated\nORA-06512: at "SPHERE_D1.PKG_RATE_TABLES_V2", line 102\nORA-06512: at "SPHERE_D1.PKG_RATE_TABLES_V2", line 54\nORA-06512: at line 1' }
Using the following code to validate :
let valid = ajv.validate(schema, res);
var detailedErrorMsg = "\n" + ajv.errorsText(ajv.errors, { separator: "\n" }) + "\n";
console.log(detailedErrorMsg);
AJV should return error as schema and response are different, but AJV is returning 'no errors'.
Is there any problem with the code ?
This is resolved by adding required feilds in schema definition.
{
"$id": "create-offer.json#",
"description": "",
"title": "",
"type": "object",
"required": [
/*mention objects which should be requird*/
]
}
Related
I am looking for a Javascript library to list the possible Json Paths based on a Json Schema.
For a json schema like below, I want to list the possible json paths.
{
"$id": "https://example.com/person.schema.json",
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Customer",
"type": "object",
"properties": {
"firstName": {
"type": "string",
"description": "The person's first name."
},
"lastName": {
"type": "string",
"description": "The person's last name."
},
"age": {
"description": "Age in years which must be equal to or greater than zero.",
"type": "integer",
"minimum": 0
},
"address": {
"type": "object",
"city": {
"type": "string",
},
"country": {
"type": "string",
}
}
}
}
Possible Json Paths: firstName, lastName, age, address.city, and address.country
Based on #customcommander's answer
Add support for $ref (prevent recursion)
Add hierarchy parents paths too (i.e. a.b.c -> a + a.b + a.b.c)
Add support for array items (using [] as a generic indexer)
const _derivePathsFromSchema = (schema, properties, defined) => {
let paths = [];
if (!properties) return paths;
return Object.keys(properties).reduce((paths, childKey) => {
let child = properties[childKey];
const { $ref, ...childProperties } = child;
if ($ref?.startsWith('#/definitions/')) {
const definition = $ref.substr($ref.lastIndexOf('/') + 1);
if (!defined.includes(definition)) // prevent recursion of definitions
{
defined.push(definition);
child = {
...schema.definitions[definition], // load $ref properties
...childProperties, // child properties override those of the $ref
};
}
}
if (child.type === 'object') {
return paths.concat(childKey, _derivePathsFromSchema(schema, child.properties, defined.slice()).map(p => `${childKey}.${p}`));
}
if (child.type === 'array' && child.items?.properties) {
return paths.concat(childKey, `${childKey}[]`, _derivePathsFromSchema(schema, child.items.properties, defined.slice()).map(p => `${childKey}[].${p}`));
}
return paths.concat(childKey);
}, paths);
};
const derivePathsFromSchema = schema => _derivePathsFromSchema(schema, schema.properties, []);
console.log(derivePathsFromSchema({
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"BType": {
"type": "object",
"properties": {
"a": {
"$ref": "#/definitions/AType"
}
}
},
"AType": {
"type": "object",
"properties": {
"b": {
"$ref": "#/definitions/BType"
}
}
}
},
"type": "object",
"properties": {
"a": {
"$ref": "#/definitions/AType"
},
"b": {
"$ref": "#/definitions/BType"
},
"id": {
"type": "string"
},
"array": {
"type": "array",
"items": {
"type": "object",
"properties": {
"item": { "type": "string" }
}
}
},
"obj": {
"type": "object",
"properties": {
"nested": { "type": "string" }
}
}
}
}));
You don't necessarily need a library for that. You can use a simple recursive function:
var schema = {
"$id": "https://example.com/person.schema.json",
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Customer",
"type": "object",
"properties": {
"firstName": {
"type": "string",
"description": "The person's first name."
},
"lastName": {
"type": "string",
"description": "The person's last name."
},
"age": {
"description": "Age in years which must be equal to or greater than zero.",
"type": "integer",
"minimum": 0
},
"address": {
"type": "object",
"properties": {
"city": {
"type": "string",
},
"country": {
"type": "string",
}
}
}
}
};
var path = ({properties}) =>
Object.keys(properties).reduce((acc, key) =>
acc.concat(properties[key].type !== 'object' ? key :
path(properties[key]).map(p => `${key}.${p}`)), []);
console.log(
path(schema)
);
I have the following jsonSchema: (note that there are fields called 'properties' and its not 'json-schema peoperties(who represent fields)'
{
"type": "object",
"properties": {
"name": {
"type": "string"
},
"image": {
"type": "string",
"media": {
"binaryEncoding": "base64",
"type": "image/jpeg"
}
},
"properties": {
"type": "string"
},
"nameObj": {
"type": "object",
"properties": {
"properties": {
"type": "string"
},
"firstName": {
"title": "First Name",
"type": "string",
"maxLength": 100
}
}
}
}
}
data looks like:
{
"name": "person1",
"properties": "myProperties",
"nameObj": {
"properties": "nameProperties",
"firstName:": "myPerson"
}
}
I have dotnotation path to field "firstName" under the schema:
properties.nameObj.properties.firstName
and I want to convert it to data path as below:
nameObj.firstName
I cant only ignore 'properties' fields because (as you can see in above schema) 'properties' can be a data field name or a json-schema property.
JaveScript example will be greate.
Thanks
Ive crated a function to convert this path:
function schemaPathToEntityPath(schema,path) {
let fields = path.split('.');
let dataFields;
for (let field of fields) {
if (field === 'properties') {
//if its json-schema property
if (schema.hasOwnProperty('type') && schema.type === 'object') {
//go next level inside schema
schema = schema[field];
continue;
}
}
//if field actually exist in schema
if(schema.hasOwnProperty(field)) {
//go next level inside schema
schema = schema[field];
//for the first time just add field, later add '.' + field
dataFields = dataFields ? dataFields += '.' + field : field;
}
}
return dataFields;
}
example:
let schema={
"type": "object",
"properties": {
"name": {
"type": "string"
},
"image": {
"type": "string",
"media": {
"binaryEncoding": "base64",
"type": "image/jpeg"
}
},
"properties": {
"type": "string"
},
"nameObj": {
"type": "object",
"properties": {
"properties": {
"type": "string"
},
"firstName": {
"type": "string",
"maxLength": 100
}
}
}
}
}
let schemaPath1='properties.nameObj.properties.firstName'
let schemaPath2='properties.nameObj.properties.properties'
console.log(schemaPathToEntityPath(schema,schemaPath1));
//output= nameObj.firstName
console.log(schemaPathToEntityPath(schema,schemaPath2));
//output= nameObj.properties
Getting Schema <[object Object]> already exists with different definition error while trying to refer 2 schemas in one.
Please correct me if am doing something wrong:
Coupons Schema in coupons.js
const COUPONS_SCHEMA = {
"id": "/Coupons",
"items": {
"id": "/items",
"properties": {
"Description": {
"type": "string"
},
"Ean": {
"type": "string"
},
"ExpiryDate": {
"type": "string"
},
"Id": {
"type": "string"
},
"Name": {
"type": "string"
},
"StartDate": {
"type": "string"
},
"Type": {
"type": "string"
},
"VoucherValue": {
"type": "string"
}
},
"type": "object"
},
"type": "array"
};
export default COUPONS_SCHEMA;
Rewards Schema in rewards.js
const REWARDS_SCHEMA = {
"id": "/Rewards",
"items": {
"id": "/items",
"properties": {
"PromotionId": {
"type": "string"
},
"Reward Amount": {
"type": "string"
},
"RewardType": {
"type": "string"
}
},
"type": "object"
},
"type": "array"
};
export default REWARDS_SCHEMA;
Am referencing above defined schemas in Discounts Schema
import { Validator } from 'jsonschema';
import Coupons from './coupons';
import Rewards from './rewards';
let validator = new Validator();
const DISCOUNTS_SCHEMA = {
"id": "/Discounts",
"properties": {
"Coupons": {
"$ref": "/Coupons"
},
"PromotionalClubCardPoints": {
"type": "string"
},
"Rewards": {
"$ref": "/Rewards"
},
"StaffDiscount": {
"type": "string"
},
"StandardClubCardPoints": {
"type": "string"
},
"TotalClubCardPoints": {
"type": "string"
},
"TotalCoupons": {
"type": "string"
},
"TotalGiftCards": {
"type": "string"
},
"TotalGreenClubCardPoints": {
"type": "string"
},
"TotalSavings": {
"type": "string"
},
"TotalVouchers": {
"type": "string"
}
},
"type": "object"
};
validator.addSchema(Coupons,'/Discounts');
validator.addSchema(Rewards,'/Discounts');
export default DISCOUNTS_SCHEMA;
and getting the below error
throw new Error('Schema <'+schema+'> already exists with different definition');
^
Error: Schema <[object Object]> already exists with different definition
at Validator.addSubSchema (/Users/repo/node_modules/jsonschema/lib/validator.js:72:15)
at Validator.addSubSchemaArray (/Users/repo/node_modules/jsonschema/lib/validator.js:99:10)
at Validator.addSubSchema (/Users/repo/node_modules/jsonschema/lib/validator.js:80:8)
at Validator.addSchema (/Users/repo/node_modules/jsonschema/lib/validator.js:48:8)
at Object.<anonymous> (/Users/repo/src/schema/discounts.js:47:11)
at Module._compile (module.js:570:32)
at loader (/Users/repo/node_modules/babel-register/lib/node.js:144:5)
at Object.require.extensions.(anonymous function) [as .js] (/Users/repo/node_modules/babel-register/lib/node.js:154:7)
at Module.load (module.js:487:32)
at tryModuleLoad (module.js:446:12)
Please correct me if am doing something wrong in defining schemas.
The problem is probably that you use the id "/items" in both coupons.js and rewards.js. ids need to be universally unique. That is why they are supposed to be absolute URIs.
In my case (anyone else landing here to find similar issue),
we had a schema file in this format:
{
"keyA": {
"type": "string",
"example": "0319739002",
"id": "/keyA",
"minLength": 1,
"maxLength": 100
},
"keyB": {
"keyA": {
"type": "string",
"example": "0186013001",
"id": "/keyA",
"minLength": 1,
"maxLength": 100
}
}
}
where keyA was a part of keyB, but the id was repeated. Removing (/renaming) the 'id' field worked for us.
I am having a query parsing exception. I am using javascript. My configuration is present in elastic.js file.
I am getting results if I remove the filtered part. But if I add it, I am getting the exception
var client = require('./elastic.js');
client.search({
index: 'test-2017.03.25',
size: 0,
body: {
query: {
bool: {
must: {
match: {
status: 502,
}
},
},
filtered: {
query: {
range: {
timestamp: {'gt': 1490380200000}
}
}
}
}
}
}, function (error, response, status) {
if (error) {
console.log("search error: " + error)
}
else {
console.log("--- Response ---");
console.log(response);
console.log("--- Hits ---");
response.hits.hits.forEach(function (hit) {
console.log(hit);
})
}
});
This is my object mappings:
"test-2017.03.02": {
"mappings": {
"log": {
"properties": {
"#timestamp": {
"type": "date",
"format": "strict_date_optional_time||epoch_millis"
},
"#version": {
"type": "string"
},
"beat": {
"properties": {
"hostname": {
"type": "string"
},
"name": {
"type": "string"
}
}
},
"body_bytes_sent": {
"type": "string"
},
"count": {
"type": "long"
},
"fields": {
"properties": {
"label": {
"type": "string"
}
}
},
"host": {
"type": "string"
},
"http_referrer": {
"type": "string"
},
"http_user_agent": {
"type": "string"
},
"input_type": {
"type": "string"
},
"message": {
"type": "string"
},
"offset": {
"type": "long"
},
"remote_addr": {
"type": "string"
},
"remote_user": {
"type": "string"
},
"request": {
"type": "string"
},
"request_method": {
"type": "string"
},
"request_time": {
"type": "double"
},
"source": {
"type": "string"
},
"status": {
"type": "string"
},
"tags": {
"type": "string"
},
"time": {
"type": "string"
},
"type": {
"type": "string"
}
}
}
}
}
I want to get that data based on status and request and filter using the timestamp field.
I am getting the following error:
search error: [parse_exception] failed to parse search source. expected field name but got [START_OBJECT]
Please help.
Sample Document :
{
"_index": "test-2017.03.25",
"_type": "log",
"_id": "JI9u8hGG8y8gGUk",
"_score": 1.0,
"_source": {
"#version": "1",
"#timestamp": "2017-03-25T00:00:01.617Z",
"count": 1,
"offset": 1114273370,
"type": "log",
"input_type": "log",
"fields": {
"label": "test"
},
"source": "/var/log/nginx/access.log",
"tags": [
"_grokparsefailure"
],
"time": "25/Mar/2017:05:30:00 +0530",
"body_bytes_sent": "81",
"request_time": 0.052,
"status": "200",
"request": "GET /api/test?status=test HTTP/1.1",
"request_method": "GET",
"http_referrer": "-",
"http_user_agent": "Java/1.8.0_31"
}
}
Your query is not valid, change it to this:
client.search({
index: 'test-2017.03.25',
size: 0,
body: {
query: {
bool: {
filter: [
{
match: {
status: 502,
}
},
{
range: {
'#timestamp': {'gt': 1490380200000}
}
}
]
}
}
}
I have json schema definition like this:
(Update: basically its draft 03 format: http://json-schema.org/draft-03/schema#)
{
"$schema": "http://json-schema.org/draft-03/schema",
"product": {
"name": {
"required": true,
"type": "string"
},
"description": {
"required": true,
"type": "string"
}
},
"type": "object"
}
But I need it in this format(standard json schema structure), which is draft 04 format(http://json-schema.org/draft-04/schema#)
{
"type": "object",
"properties": {
"product": {
"type": "object",
"required": [
"name",
"description"
],
"properties": {
"name": {
"type": "string"
},
"description": {
"type": "string"
}
}
}
},
"required": [
"product"
]
}
Is there any converter to convert the above format to this one? I just don't want to manually do it which might be error prone.
I haven't used it, so I can't vouch for it personally, but there is conversion tool.
https://github.com/geraintluff/json-schema-compatibility