setting required on a json-schema array - json

I am trying to figure out how to set required on my json-schema array of objects. The required property works fine on an object just not an array.
Here is the items part of my json schema:
"items": {
"type": "array",
"properties": {
"item_id": {"type" : "number"},
"quantity": {"type": "number"},
"price": {"type" : "decimal"},
"title": {"type": "string"},
"description": {"type": "string"}
},
"required": ["item_id","quantity","price","title","description"],
"additionalProperties" : false
}
Here is the json array I am sending over. The json validation should fail since I am not passing a description in these items.
"items": [
{
"item_id": 1,
"quantity": 3,
"price": 30,
"title": "item1 new name"
},
{
"item_id": 1,
"quantity": 16,
"price": 30,
"title": "Test Two"
}
]

I got it to work using this validator by nesting the part of the schema for the array elements inside a object with the name items. The schema now has two nested items fields, but that is because one is a keyword in JSONSchema and the other because your JSON actually has a field called items
JSONSchema:
{
"type":"object",
"properties":{
"items":{
"type":"array",
"items":{
"properties":{
"item_id":{
"type":"number"
},
"quantity":{
"type":"number"
},
"price":{
"type":"number"
},
"title":{
"type":"string"
},
"description":{
"type":"string"
}
},
"required":[
"item_id",
"quantity",
"price",
"title",
"description"
],
"additionalProperties":false
}
}
}
}
JSON:
{
"items":[
{
"item_id":1,
"quantity":3,
"price":30,
"title":"item1 new name"
},
{
"item_id":1,
"quantity":16,
"price":30,
"title":"Test Two"
}
]
}
Output with two errors about missing description fields:
[ {
"level" : "error",
"schema" : {
"loadingURI" : "#",
"pointer" : "/properties/items/items"
},
"instance" : {
"pointer" : "/items/0"
},
"domain" : "validation",
"keyword" : "required",
"message" : "missing required property(ies)",
"required" : [ "description", "item_id", "price", "quantity", "title" ],
"missing" : [ "description" ]
}, {
"level" : "error",
"schema" : {
"loadingURI" : "#",
"pointer" : "/properties/items/items"
},
"instance" : {
"pointer" : "/items/1"
},
"domain" : "validation",
"keyword" : "required",
"message" : "missing required property(ies)",
"required" : [ "description", "item_id", "price", "quantity", "title" ],
"missing" : [ "description" ]
} ]
Try pasting the above into here to see the same output generated.

I realize this is an old thread, but since this question is linked from jsonschema.net, I thought it might be worth chiming in...
The problem with your original example is that you're declaring "properties" for an "array" type, rather than declaring "items" for the array, and then declaring an "object" type (with "properties") that populates the array. Here's a revised version of the original schema snippet:
"items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"item_id": {"type" : "number"},
"quantity": {"type": "number"},
"price": {"type" : "decimal"},
"title": {"type": "string"},
"description": {"type": "string"}
},
"required": ["item_id","quantity","price","title","description"],
"additionalProperties" : false
}
}
I would recommend against using the term "items" for the name of the array, to avoid confusion, but there's nothing stopping you from doing that...

Maybe your validator only supports JSONSchema v3?
The way required works changed between v3 and v4:
In v3 required is a boolean: https://datatracker.ietf.org/doc/html/draft-zyp-json-schema-03#section-5.7
In v4 required is an array of strings (like in your example): https://datatracker.ietf.org/doc/html/draft-fge-json-schema-validation-00#section-5.4.3

In Python, for me it worked like this:
schema = {
"type": "object",
"properties": {
"price": {"type": "number"},
"name": {"type": "string", 'required': True}, # set require = True
"details": {"type": "object"},
}
}

Related

How to $ref an object from within an array in the same JSON file

I would like to declare and define an array of my own objects but I am having problems validating the instance the way I expect.
My $ref points to an object in the same schema (as specified here you can only point to a schema; Can JSON integer attributes be referenced?)
I have followed this link for guidance; https://spacetelescope.github.io/understanding-json-schema/structuring.html
I am validating here; http://json-schema-validator.herokuapp.com/
I would like to make the schema stricter by not allowing further elements of other kinds in the feeder_tx array but can't seem to get the syntax right.
This is the schema:
{
"id": "params-schema",
"$schema": "http://json-schema.org/draft-04/schema#",
"description": "my schema",
"definitions": {
"tx": {
"type": "object",
"properties": {
"comment": {"type": "string"},
"max_channels": {
"type": "integer",
"minimum" : 0,
"maximum" : 10000,
"additionalProperties": false
}
},
"additionalProperties": false,
"required": ["max_channels"]
}
},
"type": "object",
"properties": {
"feeder_tx": {
"type": "array",
"minItems": 1,
"maxItems": 4,
"items": {
"type": "object",
"properties": {
"comment": {"type": "string"},
"info": {
"$ref": "#/definitions/tx",
"additionalProperties": false
}
}
}
}
},
"required": ["feeder_tx"]
}
This is the instance:
{
"feeder_tx": [
{"lala": 25, "max_channels": 1499}
]
}
Which I would like to fail because of the addition of lala but instead it validates successfully.
If I add an "additionalProperties": false at the end of the "properties" section of items the validator complains about both "lala" and "max_channels".
This makes sense because the next level is "info"
[ {
"level" : "error",
"schema" : {
"loadingURI" : "#",
"pointer" : "/properties/feeder_tx/items"
},
"instance" : {
"pointer" : "/feeder_tx/0"
},
"domain" : "validation",
"keyword" : "additionalProperties",
"message" : "object instance has properties which are not allowed by the schema: [\"lala\",\"max_channels\"]",
"unwanted" : [ "lala", "max_channels" ]
} ]
If I try to make the instance refer to "info" the following error occurs:
[ {
"level" : "fatal",
"message" : "URI \"params-schema#\" is not absolute",
"uri" : "params-schema#",
"info" : "other messages follow (if any)"
} ]
for this instance data:
{
"feeder_tx": [
{"info": { "max_channels": 1499}}
]
}
In fact, I do not see why I need to have a feeder_tx/items/info object as the thing I am $refing is an object.
So I revert the instance data back and remove this object. The following error occurs:
[ {
"level" : "fatal",
"message" : "URI \"params-schema#\" is not absolute",
"uri" : "params-schema#",
"info" : "other messages follow (if any)"
} ]
I.e the schema and instance becomes this:
"type": "object",
"properties": {
"feeder_tx": {
"type": "array",
"minItems": 1,
"maxItems": 4,
"items": {
"$ref": "#/definitions/tx"
}
}
},
Can someone please explain what is happening here, and the correct way to do it?
Restructuring the schema to not use $ref can solve the problem but I would like to know how to do it with references.
{
"id": "params-schema",
"$schema": "http://json-schema.org/draft-04/schema#",
"description": "parameters schema",
"type": "object",
"properties": {
"feeder_tx": {
"type": "array",
"minItems": 1,
"maxItems": 4,
"items": {
"type": "object",
"properties": {
"comment": {"type": "string"},
"max_channels": {
"type": "integer",
"minimum" : 0,
"maximum" : 10000,
"additionalProperties": false
}
},
"additionalProperties": false,
"required": ["max_channels"]
}
}
},
"required": ["feeder_tx"]
}
gives the correct validation error:
[ {
"level" : "error",
"schema" : {
"loadingURI" : "#",
"pointer" : "/properties/feeder_tx/items"
},
"instance" : {
"pointer" : "/feeder_tx/0"
},
"domain" : "validation",
"keyword" : "additionalProperties",
"message" : "object instance has properties which are not allowed by the schema: [\"lala\"]",
"unwanted" : [ "lala" ]
} ]
Thanks.
This works:
{
"id": "#",
"$schema": "http://json-schema.org/draft-04/schema#",
"description": "parameters schema",
"definitions": {
"item": {
"type": "object",
"properties": {
"comment": {
"type": "string"
},
"max_channels": {
"type": "integer",
"minimum": 0,
"maximum": 10000,
"additionalProperties": false
}
},
"additionalProperties": false,
"required": [
"max_channels"
]
}
},
"type": "object",
"properties": {
"feeder_tx": {
"type": "array",
"minItems": 1,
"maxItems": 4,
"items": {
"$ref": "#/definitions/item"
}
}
},
"required": [
"feeder_tx"
]
}
Tried using:
http://www.jsonschemavalidator.net/
https://jsonschemalint.com/#/version/draft-04/markup/json
https://json-schema-validator.herokuapp.com/

Bigquery importing map's json data into a table

I have a json file which has data from a pojo, which is basically
String
Map<String, Set<OBJ>>
=> where object has
int
int
string
timestamp
Here is a sample row:
{"key":"123qwe123","mapData":{"3539":[{"id":36,"type":1,"os":"WINDOWS","lastSeenDate":"2015-06-03 22:46:38 UTC"}],"16878":[{"id":36,"type":1,"os":"WINDOWS","lastSeenDate":"2015-06-03 22:26:34 UTC"}],"17312":[{"id":36,"type":1,"os":"WINDOWS","lastSeenDate":"2015-06-03 22:26:48 UTC"}]}}
I tried to do following schema, but thats not working:
[
{
"name" : "key",
"type" : "string"
},
{
"name" : "mapData",
"type" : "record",
"mode": "repeated",
"fields": [
{
"name": "some_id",
"type": "record",
"mode" : "repeated",
"fields" : [
{
"name": "id",
"type": "integer",
"mode": "nullable"
},
{
"name": "type",
"type": "integer",
"mode": "nullable"
},
{
"name": "os",
"type": "string",
"mode": "nullable"
},
{
"name": "lastSeenDate",
"type": "timestamp",
"mode": "nullable"
}
]
}
] } ]
When i run i get: repeated record must be imported as a JSON array
I know something is up with schema but not figured out yet.

Defining key-value pairs from schema to json

I am trying to define an object with key value pairs from a JSON schema and validating it at: Json Schema Validator but I am having no joy as there does not seem to be instructions to do so in all the JSON schema sites I have looked up.
My object schema definition is as follows:
"gum guards" : {
"type": "object",
"properties": {
"Color": { "type": "string" },
"product code": { "type": "string" },
"color code": { "type": "string"}
},
"enum" : ["Color", "product code", "color code"]
}
The resulting JSON file should give me values such as:
"gum guards" : [
{ "Color" : "Black", "product code" : "gg-7890", "color code" : "#000000" },
{ "Color" : "White", "product code" : "gg-7891", "color code" : "#ffffff" }
]
However, the validator is giving me the following error message:
[ {
"level" : "error",
"schema" : {
"loadingURI" : "#",
"pointer" : ""
},
"instance" : {
"pointer" : ""
},
"domain" : "validation",
"keyword" : "type",
"message" : "instance type (object) does not match any allowed primitive type (allowed: [\"array\"])",
"found" : "object",
"expected" : [ "array" ]
} ]
How do you define an array with key-value/pairs in JSON schema?
SCHEMA:
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "List of products",
"type": "array",
"items": {
"title": "Product",
"type": "object",
"properties": {
"id": {
"description": "The unique identifier for a product",
"type": "number"
},
"Category" : {
"type": "string"
},
"Product Name" : {
"type" : "string"
},
"gum guards" : {
"type": "array",
"items": {
"Color": { "type": "string" },
"product code": { "type": "string" },
"color code": { "type": "string"}
},
"required" : ["Color", "product code", "color code"]
},
"Summary" : {
"type": "object",
"properties": {
"Description": {
"oneOf": [
{"$ref" : "json/product_summary.json#1110/description"},
{"$ref" : "json/product_summary.json#1111/description"},
{"$ref" : "json/product_summary.json#1112/description"},
{"$ref" : "json/product_summary.json#1114/description"},
]
}
}
}
}
}
OUTPUT:
{
"id" : 1110,
"Device Type" : "handset",
"Product Name" : "Pack of accessories",
"variants" : [
{ "Color" : "Black", "product code" : "gg-09090", "color code" : "#000000" },
{ "Color" : "White", "product code" : "gg-09091", "color code" : "#ffffff" }
],
"Summary" : {
"description" : "Pack of fighter products with chosen colour guard"
}
}
The issue is here:
"gum guards" : {
"type": "object",
You've declared that "gum guards" must be an object, like:
"gum guards": {"Color" : ...},
If you want "gum guards" to be an array, then use "type": "array", and specify the schema for the items using "items":
"gum guards": {
"type": "array",
"items": {
"type": "object",
"properties": {...},
"required": ["Color", "product code", "color code"]
}
}
(I've also corrected "enum" to "required", because that looked like a mistake.)

JSON.Net: Schema validates where it shouldn't when using anyOf

I'm trying to detect if the user specified a boolean as a string instead of a real boolean.
I'm testing commentsModule/enabled to see if the value is false, once with quotes and once without.
The online validator: http://json-schema-validator.herokuapp.com/ works correctly, and identifies the failure as "instance value (\"false\") not found in enum (possible values: [false])".
However, NewtonSoft Json (latest version) with exactly the same schema and json defines this as a valid json.
Schema:
{
"$schema":"http://json-schema.org/draft-04/schema#",
"description": "pages json",
"type": "object",
"properties":
{
"name": {"type":"string"},
"description": {"type":"string"},
"channel": {"type":"string"},
"commentsModule":{
"type": "object",
"anyOf":[
{ "$ref": "#/definitions/commentsModuleDisabled" }
]
}
},
"definitions":{
"commentsModuleDisabled":{
"required": [ "enabled" ],
"properties": {
"enabled": { "type": "boolean", "enum": [ false ] }
}
}
}
}
(using oneOf gives the same result)
JSON:
{
"_id": {
"$oid": "530dfec1e4b0ee95f0f3ce11"
},
"pageId": 1234,
"pageType": "Show",
"name": "my name",
"description": "this is decription.” ",
"channel": "tech",
"commentsModule": {
"CaptionFieldDoesntExist": "Comments",
"enabled": "false"
},
"localInstance": "com",
"productionYear": "2014",
"navbarCaptionLink": "",
"logoAd": ""
}
Json.Net code (taken from the official site):
JsonSchema schema = JsonSchema.Parse(schemaJson);
JObject jsonToVerify = JObject.Parse(json);
IList<string> messages;
bool valid = jsonToVerify.IsValid(schema, out messages);
Thank you!
EDIT:
Json.Net doesn't support Json Schema v4, so the "definitions" references are ignored.
For example, in this case the "caption" is checked for minimal length of 1, and has 0, but Json.net passes validation:
JSON
{
"_id": {
"$oid": "530dfec1e4b0ee95f0f3ce11"
},
"pageId": 1234,
"pageType": "Show",
"name": "another name",
"description": "description ",
"channel": "tech",
"commentsModule": {
"caption": "",
"enabled": true
},
"localInstance": "com",
"productionYear": "2014",
"navbarCaptionLink": "",
"logoAd": "" }
Schema:
{
"$schema":"http://json-schema.org/draft-04/schema#",
"description": "pages json",
"type": "object",
"properties":
{
"name": {"type":"string"},
"description": {"type":"string"},
"channel": {"type":"string"},
"commentsModule":{
"type": "object",
"oneOf":[
{ "$ref": "#/definitions/commentsModuleDisabled" },
{ "$ref": "#/definitions/commentsModuleEnabled" }
]
}
},
"definitions":{
"commentsModuleDisabled":{
"required": [ "enabled" ],
"properties": {
"enabled": { "type": "boolean", "enum": [ false ] }
}
},
"commentsModuleEnabled":{
"required": [ "enabled", "caption" ],
"properties": {
"enabled": { "type": "boolean", "enum": [ true ] },
"caption": { "type": "string", "minLength": 1 }
}
}
} }
the error from the online tool in this case talks about mismatches for both schemas and refers to the minimal length requirement:
"message" : "instance failed to match exactly one schema (matched 0 out of 2)"
... "message" : "string \"\" is too short (length: 0, required minimum: 1)",
Json.Net doesn't support Json Schema v4, only v3. That's why "anyOf" and "definitions" are not recognized and the validation passes.
Update:
Json.NET Schema has full support for Draft 4.

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