Json Schema example for oneOf objects - json

I am trying to figure out how oneOf works by building a schema which validates two different object types. For example a person (firstname, lastname, sport) and vehicles (type, cost).
Here are some sample objects:
{"firstName":"John", "lastName":"Doe", "sport": "football"}
{"vehicle":"car", "price":20000}
The question is what have I done wrongly and how can I fix it. Here is the schema:
{
"description": "schema validating people and vehicles",
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"required": [ "oneOf" ],
"properties": { "oneOf": [
{
"firstName": {"type": "string"},
"lastName": {"type": "string"},
"sport": {"type": "string"}
},
{
"vehicle": {"type": "string"},
"price":{"type": "integer"}
}
]
}
}
When I try to validate it in this parser:
https://json-schema-validator.herokuapp.com/
I get the following error:
[ {
"level" : "fatal",
"message" : "invalid JSON Schema, cannot continue\nSyntax errors:\n[ {\n \"level\" : \"error\",\n \"schema\" : {\n \"loadingURI\" : \"#\",\n \"pointer\" : \"/properties/oneOf\"\n },\n \"domain\" : \"syntax\",\n \"message\" : \"JSON value is of type array, not a JSON Schema (expected an object)\",\n \"found\" : \"array\"\n} ]",
"info" : "other messages follow (if any)"
}, {
"level" : "error",
"schema" : {
"loadingURI" : "#",
"pointer" : "/properties/oneOf"
},
"domain" : "syntax",
"message" : "JSON value is of type array, not a JSON Schema (expected an object)",
"found" : "array"
} ]

Try this:
{
"description" : "schema validating people and vehicles",
"type" : "object",
"oneOf" : [
{
"type" : "object",
"properties" : {
"firstName" : {
"type" : "string"
},
"lastName" : {
"type" : "string"
},
"sport" : {
"type" : "string"
}
}
},
{
"type" : "object",
"properties" : {
"vehicle" : {
"type" : "string"
},
"price" : {
"type" : "integer"
}
},
"additionalProperties":false
}
]
}

oneOf need to be used inside a schema to work.
Inside properties, it's like another property called "oneOf" without the effect you want.

Related

Json schema validator, how to validate if key is not static

I am trying to validate this specific schema:
{
"messages": [
{
"name": "test msg",
"id": "0x100",
"signals": {
"0": {"name": "Engine RPM", "bit_length": 16},
"16": {"name": "Gear", "bit_length": 3},
"19": {"name": "Battery Voltage", "bit_length": 5}
}
}
]
}
I am using the python from jsonschema import Draft4Validator to validate this schema... however I am not sure how to continue.
This is my current schema validation so far:
{
"$schema" : "https://json-schema.org/schema#",
"type" : "object",
"properties" :
{
"messages" :
{
"type" : "array",
"items" :
{
"properties" :
{
"name" :
{
"type" : "string"
},
"id" :
{
"type" : "string"
},
"signals" :
{
"type" : "object"
},
"properties" :
{
}
},
"required": ["name", "id", "signals"]
}
}
}
}
The problem I am facing is I am not sure how to deal with the objects that are in the "signals" key as they start with a string and are NOT consistent ("0", "16", "19")... How could I go about validating this by ensuring the type is always a string, disregarding whether or not the string is consistent.
Thanks to all of those who reply in advance.
I was able to accomplish this by doing the following:
{
"$schema" : "https://json-schema.org/schema#",
"type" : "object",
"properties" :
{
"messages" :
{
"type" : "array",
"items" :
{
"properties" :
{
"name" :
{
"type" : "string"
},
"id" :
{
"type" : "string"
},
"signals" :
{
"type" : "object"
},
"properties" :
{
"start_bit" :
{
"type" : "object",
"properties" :
{
"name" :
{
"type" : "string"
},
"bit_length" :
{
"type" : "string"
},
"factor" :
{
"type" : "string"
},
"offset" :
{
"type" : "string"
}
},
"required" : ["name", "bit_length", "factor", "offset"]
}
}
},
"required": ["name", "id", "signals"]
}
}
}
}
To "avoid" having to keep the string consistent, in the validator file, I can put any string (obviously it makes more sense to name the string what is represents, in my case "start_bit") and then by NOT having it be required.

multiple properties in swagger json

I am developing an api with swagger and want in the successful response something like:
Code and subCode are under BankTransactionCode.
This is how I am trying to achieve this, by adding code and subCode as properties under BankTransactionCode
"responses" : {
"200" : {
"description" : "response description",
"schema" : {
"type" : "object",
"properties" : {
"amount" : {
"type" : "string",
"maxLength" : 25
},
"accountIBAN" : {
"type" : "string"
},
"valueDate" : {
"type" : "string",
"format" : "date"
},
**"BankTransactionCode": {
"type": "object",
"properties": {
"code": {
"type": "string",
"maxLength": 60
},
"subCode": {
"type": "string",
"maxLength": 60
}**
}
}
Unfortunately, something is not right, can anyone tell why?

For json-schema how can I declare a type for the json

How can I declare multiple schemas and let a validator select one depending on a property?
For example I would like this json to be validated against second schema for type2
{
"id2": 1,
"name": "A green door",
"price": 12.50,
"tags": ["home", "green"],
"schemaToValidate" : "type2"
}
A first schema definition for object of type1:
{
"$schema": "http://json-schema.org/draft-06/schema#",
"title": "Product",
"description": "A product from Acme's catalog",
"type": "object",
"required": ["id1"],
"schemaForType" : "type1"
}
A second schema definition for object of type2:
{
"$schema": "http://json-schema.org/draft-06/schema#",
"title": "Product",
"description": "A product from Acme's catalog",
"type": "object",
"required": ["id2"],
"schemaForType" : "type2"
}
I tried to find a sample for this at http://json-schema.org/example1.html but didn't realized if is even possible.
It's not possible to have multiple schema depending on a type but there is an alternative: change your example to use oneOf (also simplified to be easier on the schema):
{
"Type2" : {
"id2": 1
}
}
And with a schema that work on one of Type1 and Type2 can be added:
{
"description" : "schema validating Type1 and Type2",
"type" : "object",
"oneOf" : [{
"properties" : {
"Type1" : {
"type": "object",
"properties" : {
"id1" : {
"type" : "integer"
}
},
"additionalProperties": false
}
},
"required" : [ "Type1" ]
}, {
"properties" : {
"Type2" : {
"type": "object",
"properties" : {
"id2" : {
"type" : "integer"
}
},
"additionalProperties" : false
}
},
"required" : ["Type2"]
}
]
}
Another example of AnyOf

JSON schema - objects with same datatype

I generated the following JSON:
{
"someString" : "example",
"obj1" : {
"opt1" : 1,
"opt2" : 1,
"opt3" : "aaa"
},
"obj2" : {
"opt1" : 55,
"opt2" : 55,
"opt3" : "bbb"
}
}
and there will be more of objects(obj1, obj2, obj3, obj4, ...) with same data type (opt1, opt2, opt3)
now I want to create schema for this but i don't know how to combine all this objects in schema.
EDIT:
I created schema:
root: {
"type" : "object",
"oneOf" : [
{
"properties" : {
"someString" : { "type" : "string" }
},
"patternProperties" : { "^.*$" : { "$ref" : "./schemas/myPatternProperties.json#" } },
"additionalProperties" : false }
}
]
}
and myPatternProperties.json looks:
{
"type" : "object",
"properties" : {
"opt1" : { "type" : "number" },
"opt2" : { "type" : "number" },
"opt3" : { "type" : "string" },
}
"required" : [ "opt1", "opt2", "opt3" ]
}
Is there anything wrong because, my generated JSON is still not recognized as this schema type.
As I understand your problem is to describe object with a lot of properties with the same type and some naming rules. To solve that you must specify patternProperties section
{
"patternProperties": {
"^(/[^/]+)+$": { "$ref": "http://some.site.somewhere/entry-schema#" }
}
that construction specify pattern to match for properties. Example how to use patternProperties Read more at specification
UPDATE
Actually full scheme must be something like that
{
"$schema": "http://json-schema.org/draft-06/schema#",
"type": "object",
"properties": {
"someString": {
"type": "string"
}
},
"patternProperties": {
"^obj([0-9]+)$": {
"$ref": "#/definitions/objEntity"
}
},
"additionalProperties": false,
"required": [ "someString" ],
"definitions": {
"objEntity": {
"type": "object",
"properties": {
"opt1": { "type": "number" },
"opt2": { "type": "number" },
"opt3": { "type": "string" }
},
"required": ["opt1", "opt2", "opt3"]
}
}
}
Of course you can split that scheme to more than 1 file, and change links to type definitions.

Correct JSON Schema for an array of items of different type

I have an unordered array of JSON items. According to the specification https://datatracker.ietf.org/doc/html/draft-zyp-json-schema-03#section-5.5 the json schema below will only validate if the objects in the array appear IN THAT ORDER. I don't want to specify an order, just validate the objects within the array, regardless of order or number of objects. From the spec I can't seem to understand how this is done.
"transactions" : {
"type" : "array",
"items" : [
{
"type" : "object",
"properties" : {
"type" : {
"type" : "string",
"enum" : ["BUILD", "REASSIGN"]
}
}
},
{
"type" : "object",
"properties" : {
"type" : {
"type" : "string",
"enum" : ["BREAK"]
}
}
}
]
}
I asked this same question on the JSON schema google group, and it was answered quickly. User fge asked that I post his response here:
Hello,
The current specification is draft v4, not draft v3. More
specifically, the validation specification is here:
https://datatracker.ietf.org/doc/html/draft-fge-json-schema-validation-00
The web site is not up to date, I don't know why... I'll submit a pull
request.
With draft v4 you can use this:
{
"type": "array",
"items": {
"oneOf": [
{"first": [ "schema", "here" ] },
{"other": [ "schema": "here" ] }
]
}
}
For instance, this is a schema for an array where items can be either
strings or integers (it can be written in a more simple way though):
{
"type": "array",
"items": {
"oneOf": [
{"type": "string"},
{"type": "integer"}
]
}
}
This is the correct answer. My corrected schema now includes:
"transactions" : {
"type" : "array",
"items" : {
"oneOf" : [
{
"type" : "object",
"properties" : {
"type" : {
"type" : "string",
"enum" : ["BUILD", "REASSIGN"]
}
}
},
{
"type" : "object",
"properties" : {
"type" : {
"type" : "string",
"enum" : ["BREAK"]
}
}
}
]
}
}
I've been looking into this for quite a while too. But haven't been able to find a working solution. It works fine if you have only one schema eg.
"transactions" : {
"type" : "array",
"items" :
{
"type" : "object",
"properties" : {
"type" : {
"type" : "string",
"enum" : ["BREAK"]
},
}
}
Then you just skip the array brackets, and use an object. However if you want to do what you are doing, there seems to be no solid answer. This is the only thing that I've found so far: http://the-long-dark-tech-time.blogspot.se/2012/12/using-json-schema-with-array-of-mixed.html
For anyone stuck with the draft 3 schema. There is a "Type" keyword that is equivalent to the "anyOf" in draft 4:
So you can use
{
"fooBar" : {
"type" : "array",
"items" : {
"type" : [{
"type" : "object",
"properties" : {
"foo" : {
"type" : "string"
}
}
}, {
"type" : "object",
"properties" : {
"bar" : {
"type" : "string"
}
}
}
]
}
}
}
As a response to user Vdex: this is not equivalent, what you wrote means that array elements occur in this particular order within the array.
Subject to a correct implementation, if you use this schema validator.
With this schema:
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "array",
"items": [
{
"type": "boolean"
},
{
"type": "number"
},
{
"type": "string"
}
]
}
This JSON will be validated:
[
true,
5,
"a",
"6",
"a",
5.2
]
But not this one:
[
5,
true,
"a",
"6",
"a",
5.2
]
Thus, the objective is totally different from keywords like "oneOf".
In my case, I want the first element in the array has a specific format, the remain elements have another format. This is my solution:
my_schema = {
"type": "object",
"properties": {
"token": {"type": "string"},
"service_id": {"type": "string"},
"promo_code": {"type": "string"},
"path": {
"type": "array",
"items": [
{
"type": "object",
"properties": {
"address": {"type": "string"},
"lat": {"type": "number"},
"lng": {"type": "number"}
},
"required": ["address", "lat", "lng"]
},
{
"type": "object",
"properties": {
"address": {"type": "string"},
"lat": {"type": "number"},
"lng": {"type": "number"},
"district_id": {"type": "number"},
"ward_code": {"type": "number"},
"weight": {"type": "number"}
},
"required": ["address","lat", "lng","ward_code",
"district_id", "weight"]
}
]
}
},
"required": ["token", "service_id", "path"]
}
The above schema means that from the second element of the path, I required the district_id, the ward_code, the weight