How do i validate a Json file using Json schema in Mongo? - json

I have a JSON file and i want to validate the file using JSON Schema on MongoDB.
How do i import the JSON Schema to MongoDB and then validate the JSON File.
JSON file is already in one collection so i want to validate without importing a new JSON file.
JSON:
{
"Book": {
"Year:2016-2017": {
"Crs": [{
"Cr": {
"_id": {
"$oid": "5a439ff4fc0900f06fb470a4"
},
"Number": 35,
"Pag": 8,
"Desc": "Embl",
"Ad": "S",
"Type": "Embl"
}
}]
}
}
}
JSON schema:
{
"type": "object",
"$schema": "http://json-schema.org/draft-03/schema",
"id": "http://jsonschema.net",
"required": false,
"properties": {"Book": {
"type": "object",
"id": "http://jsonschema.net/Book",
"required": false,
"properties": {"Year:2016-2017": {
"type": "object",
"id": "http://jsonschema.net/Book/Year:2016-2017",
"required": false,
"properties": {"Crs": {
"type": "array",
"id": "http://jsonschema.net/Book/Year:2016-2017/Crs",
"required": false,
"items": {
"type": "object",
"id": "http://jsonschema.net/Book/Year:2016-2017/Crs/0",
"required": false,
"properties": {"Cr": {
"type": "object",
"id": "http://jsonschema.net/Book/Year:2016-2017/Crs/0/Cr",
"required": false,
"properties": {
"Ad": {
"type": "string",
"id": "http://jsonschema.net/Book/Year:2016-2017/Crs/0/Cr/Ad",
"required": false
},
"Desc": {
"type": "string",
"id": "http://jsonschema.net/Book/Year:2016-2017/Crs/0/Cr/Desc",
"required": false
},
"Number": {
"type": "number",
"id": "http://jsonschema.net/Book/Year:2016-2017/Crs/0/Cr/Number",
"required": false
},
"Pag": {
"type": "number",
"id": "http://jsonschema.net/Book/Year:2016-2017/Crs/0/Cr/Pag",
"required": false
},
"Type": {
"type": "string",
"id": "http://jsonschema.net/Book/Year:2016-2017/Crs/0/Cr/Type",
"required": false
},
"_id": {
"type": "object",
"id": "http://jsonschema.net/Book/Year:2016-2017/Crs/0/Cr/_id",
"required": false,
"properties": {"$oid": {
"type": "string",
"id": "http://jsonschema.net/Book/Year:2016-2017/Crs/0/Cr/_id/$oid",
"required": false
}}
}
}
}}
}
}}
}}
}}}
I want to validate the JSON using the schema with mongodb.

JSON file is already in one collection so i want to validate without importing a new JSON file.
As of MongoDB v3.6.x, document schema validation only occurs during updates and inserts, existing documents do not undergo validation checks until modification. This means that your existing JSON document in a MongoDB collection will not be validated by the validation rule(s) that you just applied.
Note that $jsonSchema operator and JSON-SCHEMA support is new in MongoDB version 3.6.
i want to add a new "Cr" but it needs to respect the JSON Schema.(Insertion/Update)
Once you specified a document schema validation on a collection, any update operations will trigger validation checks on the affected documents.
For example, if you have an existing document in a collection as below:
{
"_id": 1,
"a": {
"b": {
"crs": [
{
"cr": {
"d": 2,
"e": "two"
}
}
]
}
}
}
If you then apply a validator as below:
// Validator for nested array of objects.
var schema = {
"type": "object",
"properties": {
"a": {
"type": "object",
"properties": {
"b": {
"type": "object",
"properties": {
"crs": {
"type": "array",
"items": {
"type": "object",
"properties": {
"cr": {
"type": "object",
"properties": {
"d": {
"bsonType": "int",
},
"e": {
"type": "string",
}
}
}}
}
}}
}}
}}}
db.runCommand({"collMod": "collectionName",
"validator": { "$jsonSchema": schema}}
);
When you update the existing document to add a new cr, the whole document will be validated.
db.collectionName.update({_id: 1}, {"$push":{
"a.b.crs":{
"cr":{
"d": NumberInt(20),
"e": "new element"}}}
});
Any pre-existing documents that are not valid according to your document schema validation rule(s), you will have to correct the documents first before updating them.

Related

JSON Schema for child objects with different set of keys

I have JSON data of which is an array of data like
[
{
"type": "background_color",
"data": {
"backgroundColor": "F9192D"
}
},
{
"type": "banner_images",
"data": {
"images": [
{
"url": "https://example.com/abc.jpg",
"id": 3085
},
{
"url": "https://example.com/zyx.jpg",
"id": 3086
}
]
}
},
{
"type": "description_box",
"data": {
"text": "Hello 56787"
}
}
]
The data is an array of object which has two keys type and data. The type and keys of the data will be defined by the type of data it has.
Like for background_color type, the data should have backgroundColor property, while for banner_images, data should have images which is an array of other properties.
Till now, What I have done is
{
"definitions": {},
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "array",
"title": "category schema",
"description": "Used to validate data of category",
"examples": [],
"required": [],
"items": {
"type": "object",
"required": [
"type",
"data"
],
"properties": {
"type": {
"type": "string",
"enum": ["background_color", "banner_images", "description_box"]
},
"data": {
"type": "object" // How to define data property here for each use case
}
}
}
}
I'm not getting how to define the data property for each use case?
You can use if/then/else blocks to define conditional constraints.
The values of if and then are schemas. If the if schema is valid, then the then schema is applied, otherwise, the allOf subschema (allOf[0] in this example) would pass validation.
There are a few different ways to do this, but this is clean when you don't have any additional or special requirements. Please come back if you do =]
In this example, I've added banner_images...
You can test it working here.
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "array",
"title": "category schema",
"description": "Used to validate data of category",
"items": {
"type": "object",
"required": [
"type",
"data"
],
"properties": {
"type": {
"type": "string",
"enum": [
"background_color",
"banner_images",
"description_box"
]
},
"data": {
"type": "object"
}
},
"allOf": [
{
"if": {
"properties": {
"type": {
"const": "banner_images"
}
}
},
"then": {
"properties": {
"data": {
"required": [
"images"
],
"properties": {
"images": {
"type": "array"
}
}
}
}
}
}
]
}
}
For reference, here's the part of the JSON Schema draft-7 spec document that details the behaviour: https://datatracker.ietf.org/doc/html/draft-handrews-json-schema-validation-01#section-6.6

Azure logic apps Parse Json throws an error

Background
I have a custom connector which returns a JSON response .I am trying to parse the response to JSON since i want to use the response later in other flows. So that I am using Parse JSON Action from Data operations connector. Following is the JSON response and the JSON schema i provided to Parse JSON.
Response
[
[
{
"key":"Customer_Key",
"value":{
"id":"abfa48ad-392d-e511-80d3-005056b34214",
"name":"90033"
}
},
{
"key":"Status",
"value":"Done"
}
]
]
Schema
{
"type": "array",
"items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"key": {
"type": "string"
},
"value": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"name": {
"type": "string"
}
}
}
},
"required": [
"key",
"value"
]
}
}
}
Exception
{
"message": "Invalid type. Expected Object but got String.",
"lineNumber": 0,
"linePosition": 0,
"path": "[0][2].value",
"value": "90033",
"schemaId": "#/items/items/properties/value",
"errorType": "type",
"childErrors": []
},
Any one knows what is the issue on this ?How we can I convert above json response
Looks like the Use sample payload to generate schema couldn't generate right schema.
So you could go to this liquid studio site and paste the JSON payload then click the Generate Schema button, then you will get the Json Schema.
And I test the Schema, it worked perfectly.
Hope this could help you, if you still have other questions,please let me know.
Schema looks incorrect. try with the below schema:
{
"type": "array",
"items": [
{
"type": "array",
"items": [
{
"type": "object",
"properties": {
"key": {
"type": "string"
},
"value": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"name": {
"type": "string"
}
},
"required": [
"id",
"name"
]
}
},
"required": [
"key",
"value"
]
},
{
"type": "object",
"properties": {
"key": {
"type": "string"
},
"value": {
"type": "string"
}
},
"required": [
"key",
"value"
]
}
]
}
]
}

JSON Schema reporting error only for first element of array

I have the below JSON document.
[
{
"name": "aaaa",
"data": {
"key": "id",
"value": "aaaa"
}
},
{
"name": "bbbb",
"data": {
"key": "id1",
"value": "bbbb"
}
}
]
Below is the JSON Schema I have created for the above content.
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "array",
"items": [
{
"type": "object",
"properties": {
"name": {
"type": "string"
},
"data": {
"type": "object",
"properties": {
"key": {
"type": "string",
"enum": [
"id",
"temp",
]
},
"value": {
"type": "string",
}
},
"required": [
"key",
"value"
]
}
},
"required": [
"name",
"data"
]
}
]
}
As per the schema, the value of data.key is invalid for second item in the array. but any online schema validator does not find that. If we use different value in first array element, it throws the excepted error.
I assume that my schema is wrong somehow. what I expect is that any child items of the array should be reported if they have values out of the enum list.
It's an easy mistake to make, so don't beat yourself up about this one!
items can be an array or an object. If it's an array, it validates the object at that position in the instance array. Here's an excerpt from the JSON Schema spec (draft-7)
The value of "items" MUST be either a valid JSON Schema or an array of
valid JSON Schemas.
If "items" is a schema, validation succeeds if all elements in the
array successfully validate against that schema.
If "items" is an array of schemas, validation succeeds if each element
of the instance validates against the schema at the same position, if
any.
JSON Schema (validation) draft-7 items
Removing the square braces provides you with the correct schema...
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "array",
"items":
{
"type": "object",
"properties": {
"name": {
"type": "string"
},
"data": {
"type": "object",
"properties": {
"key": {
"type": "string",
"enum": [
"id",
"temp",
]
},
"value": {
"type": "string",
}
},
"required": [
"key",
"value"
]
}
},
"required": [
"name",
"data"
]
}
}

JSON-Schema oneOf for option under root area

I am trying to get the "oneof" to allow for options in root items but can't find an example and what I try gives an error.
I can get it to work if it is under another item but not under the root {'s
Example - a Job Payment that has required fields (jobNum, payee, amount, type, ) and an option for the payment type (checkInfo or dollarAmt). I know this could be done other ways, but I need this method for a more complex schema.
{
"jobNum": "x216",
"payee": "John Doe",
"type": "check",
"amount": "112.25",
"checkInfo": {
"number": "386"
}
}
{
"JobNum": "x216",
"Payee": "John Doe",
"type" : "Cash",
"amount" : "112.25",
"cashInfo" : {
"dollarAmt" : "112",
"coinAmt" : "0.25"
}
}
The following gives me this error - "Unexpected token encountered when reading value for 'oneOf'. Expected StartObject, Boolean, got StartArray"
{
"description": "Job Payment",
"type": "object",
"required": [ "jobNum", "payee", "amount", "type"],
"properties": {
"jobNum": {
"type": "string"
},
"payee": {
"type": "string"
},
"amount": {
"type": "string"
},
"type": {"enum": [ "check", "cash" ]
},
"oneOf": [
{ "$ref": "#/definitions/ptCash" },
{ "$ref": "#/definitions/ptCheck" }
]
},
"definitions": {
"ptCash": {
"properties": {
"checkInfo": {
"number": "string"
}
},
"required": [ "checkInfo" ],
"additionalProperties": false
},
"ptCheck": {
"properties": {
"dollarAmt": {
"type": "string"
},
"coinAmt": {
"type": "string"
}
},
"required": [ "dollarAmt", "coinAmt" ],
"additionalProperties": false
}
},
"additionalProperties": false
}
There are a a few issues with your schema. I fixed it for you below. I won't explain all the changes I made because I think it is mostly pretty clear by reading the schema. If you want more detail on anything, just ask and I'll update the answer with more details.
The oneOf keyword can only appear in a schema. The properties keyword is an object whose values are schemas. When you put "oneOf" directly under properties, it's not interpreted as a keyword, it's interpreted as a property called "oneOf". The validator then complains because the value of property "oneOf" is expected to be a schema, not an array of schemas like the oneOf keyword.
Your use of additionalProperties doesn't work. This keyword doesn't work the way people often assume that it does. JSON Schema keywords are not aware of any state outside of the schema they are in. Let's look at the "ptCheck" branch of your oneOf first. This describes the property "number", says it is required and that there may be no keywords other than "number". Then your top level defines a the properties "jobNum", "payee", "amount", and "type", requires them all and allows no other properties. These two things can never be true at the same time. Even though your schema is valid, there is no JSON value that can ever be valid against this schema. That's why I moved the definitions of "checkInfo" and "cashInfo" to the top level and only put the required part in oneOf. The only downside to this approach is that you can pass both a "checkInfo" and a "cachInfo" object and it will validate. The extraneous property gets ignored. There are ways around this, but they are problematic enough that I don't advise using them.
I always advise people not to use "additionalProperties": false and to ignore unknown properties instead. The reason is that JSON Schema is a constraint system. Any valid JSON is valid against the empty schema ({}) and each keyword in the schema adds some constraint. This is a different approach to what people are used to when defining classes. An empty class describes nothing and valid values are added. We use "additionalProperties": false to get JSON Schema to behave more like defining a class, but trying to get JSON Schema to behave like something it isn't causes challenges like the one you see here.
{
"description": "Job Payment",
"type": "object",
"required": ["jobNum", "payee", "amount", "type"],
"properties": {
"jobNum": { "type": "string" },
"payee": { "type": "string" },
"amount": { "type": "string" },
"type": { "enum": ["check", "cash"] },
"checkInfo": {
"type": "object",
"properties": {
"number": { "type": "string" }
},
"required": ["number"]
},
"cashInfo": {
"type": "object",
"properties": {
"dollarAmt": { "type": "string" },
"coinAmt": { "type": "string" }
},
"required": ["dollarAmt", "coinAmt"]
}
},
"oneOf": [
{ "$ref": "#/definitions/ptCash" },
{ "$ref": "#/definitions/ptCheck" }
],
"definitions": {
"ptCheck": {
"type": "object",
"properties": {
"type": { "enum": ["check"] }
},
"required": ["checkInfo"]
},
"ptCash": {
"type": "object",
"properties": {
"type": { "enum": ["cash"] }
},
"required": ["cashInfo"]
}
},
"additionalProperties": false
}
oneOf should be placed in prope
Have to re-write rule for both ptCash and ptCheck by using type: object
Following schema should work with ptCheck:
{
"description": "Job Payment",
"type": "object",
"required": [ "jobNum", "payee", "amount", "type"],
"properties": {
"jobNum": {
"type": "string"
},
"payee": {
"type": "string"
},
"amount": {
"type": "string"
},
"type": {"enum": [ "check", "cash" ]
}
},
"oneOf": [
{ "$ref": "#/definitions/ptCash" },
{ "$ref": "#/definitions/ptCheck" }
],
"definitions": {
"ptCash": {
"properties": {
"checkInfo": {
"type": "object",
"required": ["number"],
"properties": {
"number": {
"type": "string"
}
}
}
},
"required": [ "checkInfo" ]
},
"ptCheck": {
"properties": {
"cashInfo": {
"type": "object",
"properties": {
"dollarAmt": {
"type": "string"
},
"coinAmt": {
"type": "string"
}
},
"required": ["dollarAmt", "coinAmt"]
}
},
"required": ["cashInfo"]
}
}
}
Provide some example as below:
import jsonschema
import simplejson as json
schema_filename = '47926398.json'
with open(schema_filename, 'r') as f:
schema_data = f.read()
schema = json.loads(schema_data)
# validate with checkInfo
json_obj = {
"jobNum": "x216",
"payee": "John Doe",
"type": "check",
"amount": "112.25",
"checkInfo": {
"number": "386"
}
}
jsonschema.validate(json_obj, schema)
# invalidate
json_obj = {
"jobNum": "x216",
"payee": "John Doe",
"type": "check",
"amount": "112.25",
"checkInfox": {
"number": "386"
}
}
jsonschema.validate(json_obj, schema)
# validate with cashInfo
json_obj = {
"jobNum": "x216",
"payee": "John Doe",
"type": "check",
"amount": "112.25",
"cashInfo": {
"dollarAmt": "400",
"coinAmt": "30"
}
}
jsonschema.validate(json_obj, schema)
# invalidate with cashInfo
json_obj = {
"jobNum": "x216",
"payee": "John Doe",
"type": "check",
"amount": "112.25",
"cashInfox": {
"dollarAmt": "400",
"coinAmt": "30"
}
}
jsonschema.validate(json_obj, schema)
# invalidate with cashInfo.dollarAmtx
json_obj = {
"jobNum": "x216",
"payee": "John Doe",
"type": "check",
"amount": "112.25",
"cashInfo": {
"dollarAmtx": "400",
"coinAmt": "30"
}
}
jsonschema.validate(json_obj, schema)

How to support JSON schema oneOf definition using JAXB?

I was given a JSON schema which uses "oneOf" like below, is there a way to define XSD to generate the JAXB objects, which can support this "oneOf" definition of JSON data marshalling and demarshalling? I am using Jackson.
"Source": {
"description": "Indicates the source.",
"type": "object",
"oneOf": [
{
"properties": {
"Source1": {
"description": "Indicates the source 1.",
"type": "string"
}
},
"additionalProperties": false
},
{
"properties": {
"Source2": {
"description": "Indicates the source 2",
"type": "object",
"properties": {
"field1": {
"description": "filed 1 for source 1",
"type": "string"
},
"field2": {
"description": "field 2 for source 2",
"type": "string"
}
}
}
},
"additionalProperties": false
}
]
}