JSON schema: number greater than (not greater than and equal) - json

I've the following JSON config:
{
"zoomLevel": {
"min": 5,
"max": 7
}
}
The ajv validation should check if the max value is larger than the min value and can't be equal. I've found In the docs for the ajv package only the larger than or equal check and I've no idea how should I check for only the larger one. So if I use this schema:
"zoomLevel": {
"type": "object",
"properties": {
"min": {
"type": "number",
"minimum": 0
},
"max": {
"type": "number",
"minimum": {
"$data": "1/min"
},
"maximum": 18
}
}
}
it checks only if the max is larger than or equal to min. I need something like this:
"minimum": {
"$data": "1/min + 1"
},

The keyword you're looking for is exclusiveMinimum instead of minimum.
Also, note that $data is non-standard JSON Schema. This is something that ajv have decided to provide and will not be compatible with other validators.

Related

How can I specify in a json schema that a certain property is mandatory and also must contain a specific value?

I want to create several json schemas for different scenarios.
For scenario 1 I would like to specify that:
a) The property "draftenabled" must have the value true.
b) the property "draftenabled" does exist.
I have checked this post
Validating Mandatory String values in JSON Schema
and tried the following
I tried to validate this json
{
"$schema": "./test-schema.json",
"draftenabled": false,
"prefix": "hugo"
}
with this schema test-schema.json that I had created in Visual Studio Code.
{
"$schema": "http://json-schema.org/draft-04/schema#",
"properties": {
"$schema": {
"type": "string"
},
"draftenabled": {
"type": "boolean"
},
"prefix": {
"type": "string"
}
},
"additionalItems": false,
"contains": {
"properties": {
"draftenabled": {
"const": true
}
},
"required": [
"draftenabled"
]
}
}
I would have expected an error since the value for draftenabled is false rather than true.
It looks like there is some confusion around how the keywords apply to instances (data) of different types.
properties only applies to objects
additionalItems and contains only apply to arrays
Since your instance is an object, additionalItems and contains will be ignored.
Based on your description of what you want, I would do something like the following:
{
"$schema": "http://json-schema.org/draft-04/schema#",
"properties": {
"$schema": {
"type": "string"
},
"draftenabled": {
"const": "true"
},
"prefix": {
"type": "string"
}
},
"required": [
"draftenabled"
]
}
This moves the definitions you have in the contains into the main schema. You got that bit right, just in the wrong place.
You also mention that this is a "scenario 1." If there are other scenarios, I suggest creating schemas like this for each scenario then wrapping all of them together in a oneOf or anyOf:
{
"oneOf": [
{ <scenario 1> },
{ <scenario 2> },
...
]
}

JSON schema help, array of objects

I am trying to write a JSON object where the key "pStock" is the total stock of an array of bike sizes 'size'. Each size has an inventory or 'count'. I have two versions of the same code. the first one returns an error message even though the syntax looks correct to my eye.
"pStock": [
{
"size": {
"type": "string",
"count": {
"type": "number"
}
}
}
}
]
Here is the second version which returns no errors but I'm not quite sure it's saying what I want it to say.
"pStock": {
"type": ["object"],
"size": {
"type": "string",
"count": {
"type": "number"
}
}
}
EDIT 1
I appreciate all of these responses. I made a silly error in posting. Below is the correct "wrong" code that isn't working. I get the error. 'Error, schema is invalid: data/properties/pStock should be object,boolean
at Ajv.validateSchema' Rephrasing. the below code still does not work and received the error 'Error, schema is invalid: data/properties/pStock should be object,boolean
at Ajv.validateSchema'
"pStock": [
{
"size": {
"type": "string",
"count": {
"type": "number"
}
}
}
]
Any help would be greatly appreciated.
Count the opening and closing curly braces on your first JSON. It has 3 opening and 4 closing.
"pStock": [
{ // Open 1
"size": { // Open 2
"type": "string",
"count": { // Open 3
"type": "number"
} // Close 3
} // Close 2
} // Close 1
} // Close what?
]
Just remove the last one and it will work.
You are missing the closing square bracket ] on the pStock array because you have an extra brace } i.e.
"pStock": [
{
"size": {
"type": "string",
"count": {
"type": "number"
}
}
}
} <--- this is wrong
]
should be
{
"pStock":[
{
"size":{
"type":"string",
"count":{
"type":"number"
}
}
}
]
}
The first version should look like that:
"pStock": [
{
"size": {
"type": "string",
"count": {
"type": "number"
}
}
}
]
You had too many } (line 7)
The second version does not represent what you wanted, it does not contain the array of sizes.
But you can create this (pStock with multiple keys of different sizes. Then in each size write the inventory/count):
"pStock": {
"size1": {
inventory: "5",
count: 4
},
"size2": {
inventory: "5",
count: 4
}
}

In Logic Apps JSON Array while parsing throwing error for single object but for multiple objects it is working fine

While parsing JSON in Azure Logic App in my array I can get single or multiple values/objects (Box as shown in below example)
Both type of inputs are correct but when only single object is coming then it is throwing an error "Invalid type. Expected Array but got Object "
Input 1 (Throwing error) : -
{
"MyBoxCollection":
{
"Box":{
"BoxName": "Box 1"
}
}
}
Input 2 (Working Fine) : -
{
"MyBoxCollection":
[
{
"Box":{
"BoxName": "Box 1"
},
"Box":{
"BoxName": "Box 2"
}
}]
}
JSON Schema :
"MyBoxCollection": {
"type": "object",
"properties": {
"box": {
"type": "array",
items": {
"type": "object",
"properties": {
"BoxName": {
"type": "string"
},
......
.....
..
}
Error Details :-
[
{
"message": "Invalid type. Expected Array but got Object .",
"lineNumber": 0,
"linePosition": 0,
"path": "Order.MyBoxCollection.Box",
"schemaId": "#/properties/Root/properties/MyBoxCollection/properties/Box",
"errorType": "type",
"childErrors": []
}
]
I used to use the trick of injecting a couple of dummy rows in the resultset as suggested by the other posts, but I recently found a better way. Kudos to Thomas Prokov for providing the inspiration in his NETWORG blog post.
The JSON parse schema accepts multiple choices as type, so simply replace
"type": "array"
with
"type": ["array","object"]
and your parse step will happily parse either an array or a single value (or no value at all).
You may then need to identify which scenario you're in: 0, 1 or multiple records in the resultset? I'm pasting below how you can create a variable (ResultsetSize) which takes one of 3 values (rs_0, rs_1 or rs_n) for your switch:
"Initialize_ResultsetSize": {
"inputs": {
"variables": [
{
"name": "ResultsetSize",
"type": "string",
"value": "rs_n"
}
]
},
"runAfter": {
"<replace_with_name_of_previous_action>": [
"Succeeded"
]
},
"type": "InitializeVariable"
},
"Check_if_resultset_is_0_or_1_records": {
"actions": {
"Set_ResultsetSize_to_0": {
"inputs": {
"name": "ResultsetSize",
"value": "rs_0"
},
"runAfter": {},
"type": "SetVariable"
}
},
"else": {
"actions": {
"Set_ResultsetSize_to_1": {
"inputs": {
"name": "ResultsetSize",
"value": "rs_1"
},
"runAfter": {},
"type": "SetVariable"
}
}
},
"expression": {
"and": [
{
"equals": [
"#string(body('<replace_with_name_of_Parse_JSON_action>')?['<replace_with_name_of_root_element>']?['<replace_with_name_of_list_container_element>']?['<replace_with_name_of_item_element>']?['<replace_with_non_null_element_or_attribute>'])",
""
]
}
]
},
"runAfter": {
"Initialize_ResultsetSize": [
"Succeeded"
]
},
"type": "If"
},
"Process_resultset_depending_on_ResultsetSize": {
"cases": {
"Case_no_record": {
"actions": {
},
"case": "rs_0"
},
"Case_one_record_only": {
"actions": {
},
"case": "rs_1"
}
},
"default": {
"actions": {
}
},
"expression": "#variables('ResultsetSize')",
"runAfter": {
"Check_if_resultset_is_0_or_1_records": [
"Succeeded",
"Failed",
"Skipped",
"TimedOut"
]
},
"type": "Switch"
}
For this problem, I met another stack overflow post which is similar to this problem. While there is one "Box", it will be shown as {key/value pair} but not [array] when we convert it to json format. I think it is caused by design, so maybe we can just add a record "Box" at the source of your xml data such as:
<Box>specific_test</Box>
And do some operation to escape the "specific_test" in the next steps.
Another workaround for your reference:
If your json data has only one array, we can use it to do a judgment. We can judge the json data if it contains "[" character. If it contains "[", the return value is the index of the "[" character. If not contains, the return value is -1.
The expression shows as below:
indexOf('{"MyBoxCollection":{"Box":[aaa,bbb]}}', '[')
The screenshot above is the situation when it doesn't contain "[", it return -1.
Then we can add a "If" condition. If >0, do "Parse JSON" with one of the schema. If =-1, do "Parse JSON" with the other schema.
Hope it would be helpful to your problem~
We faced a similar issue. The only solution we find is by manipulating the XML before conversion. We updated XML nodes which needs to be an array even when we have single element using this. We used a Azure function to update the required XML attributes and then returned the XML for conversion in Logic Apps. Hope this helps someone.

How do you reference other property values in JSON schema?

I have a JSON schema with 2 properties, minimumTolerance and maximumTolerance. I need to make sure that the value of maximumTolerance is not smaller than minimumTolerance & vice versa. Is this possible in JSON schema?
Here is an example of what I'd like to be able to do:
{
"$schema": "http://json-schema.org/draft-06/schema#",
"title": "MinMax",
"description": "Minum & Maximum",
"type": "object",
"properties": {
"minimumTolerance":{
"type": "number"
"maximum":{
"$ref":"maximumTolerance"
}
}
"maximumTolerance":{
"type": "number"
"minumum": {
"$ref":"minimumTolerance"
}
}
}
As of Draft-7 of the specification there is no way to do this with JSON Schema.
If you are using AJV You can do this using $data and relative JSON pointers. Example:
low: {
type: 'integer',
maximum: {
$data: '1/high',
},
exclusiveMaximum: true,
},
high: {
type: 'integer',
minimum: {
$data: '1/low',
},
exclusiveMinimum: true,
},
Yes, but it may not be the dynamic answer you are looking for...put in the values of min and max for the range expected:
"MinimumTolerance": {
"type": "number",
"minimum": 0,
"maximum": 6000,
},
"MaximumTolerance": {
"type": "number",
"minimum": 6001,
},

Postman: schema validation passes even with a wrong response

I have the following schema for bellow happy path response
var responseSchema =
{
"type": "object",
"properties": {
"value": {
"type": "object",
"properties":{
"items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"patientGuid": {"type": "string" },
"givenName": {"type": "string" },
"familyName": {"type": "string" } ,
"combinedName" : {"type": "string" }
},
"required": ["patientGuid","givenName","familyName"]
}
}
}
}
}
};
Happy path response:
{
"value": {
"items": [
{
"patientGuid": "e9530cd5-72e4-4ebf-add8-8df51739d15f",
"givenName": "Vajira",
"familyName": "Kalum",
"combinedName": "Vajira Kalum"
}
],
"href": "http://something.co",
"previous": null,
"next": null,
"limit": 10,
"offset": 0,
"total": 1
},
"businessRuleResults": [],
"valid": true
}
I check if condition to validate whether response schema is correct:
if(responseBody !== null & responseBody.length >0)
{
var responseObject = JSON.parse(responseBody);
if(tv4.validate(responseObject, responseSchema))
{
// do something
}
else
{
// log some msg
}
}
Schema validation condition (nested if) get passed even when I get bellow bad response.
{
"value": {
"items": [],
"href": "http://something.co",
"previous": null,
"next": null,
"limit": 10,
"offset": 0,
"total": 0
},
"businessRuleResults": [],
"valid": true
}
Why response schema validation not failed as a response not has required fields?
When I ran your code and removed a property from the response data it seemed to work ok:
I would suggest a couple of things though - The tv4 module is not fantastic, it's not actively being worked on (for a couple of years I think) and there's a bunch of complaints/issue raised on the Postman project about how poor it is and asking for it to be replaced in the native app.
Have you considered creating a test to check the schema instead? This is very basic and could be easily refactored and wrapped in some logic but it would check the different value types of your response.
pm.test("Response data format is correct", () => {
var jsonData = pm.response.json()
// Check the type are correct
pm.expect(jsonData).to.be.an('object')
pm.expect(jsonData.value).to.be.an('object')
pm.expect(jsonData.value.items).to.be.an('array')
pm.expect(jsonData.value.items[0]).to.be.an('object')
// Check the value types are correct
pm.expect(jsonData.value.items[0].combinedName).to.be.a('string')
pm.expect(jsonData.value.items[0].givenName).to.be.a('string')
pm.expect(jsonData.value.items[0].familyName).to.be.a('string')
pm.expect(jsonData.value.items[0].patientGuid).to.a('string')
});
Also the syntax that you're using is the older style now and you don't need to JSON.parse(responseBody) the response body anymore as pm.response.json() is basically doing the same thing.