Is "type" optional in Json schema - json

{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "Product set",
"type": "array",
"items": {
"title": "Product",
"type": "object",
"properties": {
"id": {
"description": "The unique identifier for a product",
"type": "number"
},
"name": {
"type": "string"
},
"price": {
"type": "number",
"minimum": 0,
"exclusiveMinimum": true
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"minItems": 1,
"uniqueItems": true
},
"dimensions": {
"type": "object",
"properties": {
"length": {"type": "number"},
"width": {"type": "number"},
"height": {"type": "number"}
},
"required": ["length", "width", "height"]
},
"warehouseLocation": {
"description": "Coordinates of the warehouse with the product",
"$ref": "http://json-schema.org/geo"
}
},
"required": ["id", "name", "price"]
}
}
In the above Json schema "dimensions"is of "type": "object" , is type optional , if "type" is not specified should i assume it to be object. Could not find anything in specs related to optional elements.

https://datatracker.ietf.org/doc/html/draft-zyp-json-schema-03#section-5.1
If the property is not defined or is not in this list, then any
type of value is acceptable.
type is optional, ANY value is acceptable if type is omitted.

I think it is not optional. As you can see in the meta-schema below, the property "type" has no default value:
http://json-schema.org/schema
Also in my JSON Schema library NJsonSchema I set the type to None instead of Object. Check out the TypeRaw property:
https://github.com/rsuter/NJsonSchema/blob/master/NJsonSchema/JsonSchema4.Serialization.cs
When the default value is set to Object a lot more tests from the JSON Schema test suite fail. Maybe you can find a definite answer in this JSON Schema test suite:
https://github.com/json-schema/JSON-Schema-Test-Suite

Related

Issues using MinItem and uniqueItem: true to generate multiple enums

I am trying to create a JSON schema that validates a JSON object which can have more than 1 enum.
I have successfully created a JSON schema that is expected to validate a JSON object but the problem I am having is ensuring that the schema accepts more than one enum.
when I use the minItem : 3, three enums are generated but they are duplicates. when I add uniqueItem: true it only returns 1 enum instead of 3 unique enums.
My json schem:
{
"$schema": "http://json-schema.org/draft-04/schema#",
"$id": "https://mrlee.com/player.schema.json",
"title": "The lee schema",
"type": "object",
"properties": {
"AccountID":{
"description": "The unique identifier for a user",
"type": "integer"
},
"Permissions":{
"type": "object",
"properties":{
"granted":{
"type": "array",
"items": {
"type":"string",
"enum":[
"canLoginWithPassword",
"canVerify",
"canGame",
"canJump"
]
},
"minItems" : 4,
"uniqueItems": true
},
"failedConditions":{
"type": "array",
"items":[
{"type":"object",
"properties":{
"name":{
"type": "string"
},
"description":{
"type": "string"
},
"details":{
"type": "object",
"properties":{
"reason":{
"type": "string"
}
},
"required": [ "reason"]
},
"denied":{
"type": "array",
"items":{
"type":"string",
"enum":[
"canLoginWithPassword",
"canLoginWithPassword",
"canVerify",
"canGame",
"canJump"
]
},
"minItems":1,
"maxItems": 5
}
},
"required": [ "name", "description", "details","denied" ] }
]
}
},
"required": [ "granted", "failedConditions" ]
}
},
"required": [ "AccountID", "Permissions"]
to test that my json schema works, I use this link. would be glad if im pointed in the right direction as I am new to json and json schema

How do I represent polymorphic objects in JSON schema?

I'm trying to create a schema for a JSON object that varies its schema depending on the value of one of its properties: type.
Like this:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": ["INT", "PERCENT"]
}
},
"required": ["type"],
"allOf": [
{
"if": {
"properties": {"type": {"const": "INT"}}
},
"then": {
"properties": {
"value": {"type": "number", "multipleOf": 1}
},
"required": ["value"],
"additionalProperties": false
}
},
{
"if": {
"properties": {"type": {"const": "PERCENT"}}
},
"then": {
"properties": {
"value": {"type": "number"},
"min": {"type": "number"},
"max": {"type": "number"}
},
"required": ["value", "min", "max"],
"additionalProperties": false
}
}
]
}
But I'm getting all sorts of misbehaviour from the various validators I'm trying.
Some examples with problems noted after the //:
{
"type": "PERCENT", // property type has not been defined(?!)
"value": 0.0,
"min": 10,
"max": 25
}
{
"type": "INT", // no errors allowed, and value
"value": 0.1, // should've been flagged as not multiple of 1
"min": 10, // should've been flagged as disallowed additional property
"max": 25 // same as above
}
Here's the validator I'm trying
Thanks in advance for your help!
It seems that you've figured out that the problem is that addtionalProperties only considers the properties defined in the sub-schema it's defined in. That's why you have to include the "type" property in your then. You have a few options that are an improvement over the solution you posted that you weren't happy with.
Option 1: unevaluatedProperties
Draft 2019-09 introduced the unevaluatedProperties keyword. If you use this at the top level of your schema and don't use addtionalProperties anywhere, you will get the behavior you expected from additionalProperties. I see you are using draft-07, so you have to upgrade in order to use this solution.
Option 2: Boolean schemas
The solution you came up with is to re-define the "type" property in the then schemas. additionalProperties just needs "type" to be declared, you don't need to include the schema for it again. You can use true or the empty schema {} instead.
Option 3: propertyNames
Instead of additionalProperties you can use propertyNames. This allows you to declare a list of which property names are allowed in the object rather than hacking additionalProperties with true or {} to figure out the allowed property names the way you want it to.
well I found a way to get what I wanted, but it doesn't mean I like it. Having to redefine "type" doesn't seem right to me.
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": ["INT", "PERCENT"]
}
},
"required": ["type"],
"allOf": [
{
"if": {
"properties": {"type": {"const": "INT"}}
},
"then": {
"properties": {
"value": {"type": "number", "multipleOf": 1},
"type": {"type": "string"}
},
"required": ["value", "type"],
"additionalProperties": false
}
},
{
"if": {
"properties": {"type": {"const": "PERCENT"}}
},
"then": {
"properties": {
"value": {"type": "number"},
"min": {"type": "number"},
"max": {"type": "number"},
"type": {"type": "string"}
},
"required": ["value", "min", "max", "type"],
"additionalProperties": false
}
}
]
}
tests...
This validates:
{
"type": "PERCENT",
"value": 0,
"min": 10,
"max": 20
}
so does this:
{
"type": "INT",
"value": 0
}
this errors in the way I want:
{
"type": "INT",
"value": 0.1, // not a multiple of 1
"min": 4, // not expected
"max": 5 // not expected
}
and so does this:
{
"type": "PERCENT",
"value": 0.1,
"max": 5 // min is a required property
}

JSON Schema Custom Definition

Can I have a custom specifier/attribute like "required" keyword to decorate my Json schema fields with custom specifications.
Like for example:
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "Product",
"description": "A product from Acme's catalog",
"type": "object",
"properties": {
"id": {
"description": "The unique identifier for a product",
"type": "integer"
},
"name": {
"description": "Name of the product",
"type": "string"
},
"price": {
"type": "number",
"minimum": 0,
"exclusiveMinimum": true
},
"**credit-card**": {
"**type**": "**number**",
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"minItems": 1,
"uniqueItems": true
}
},
"required": ["id", "name", "price"],
"**confidential**" : ["**credit-card**"]
}
Can I have a special keyword called "confidential" to make sure that "credit-card" should not be revealed and/or masked? Does the schema standards allow for such custom metadata keywords?
It depends on the library you will use to execute the validation. I've used AJV, it allows you to define custom keywords, you can find more information about it here.

Future proof JSON schema

Is it possible to force known objects ("enemy" and "friend") to be defined while other objects are allowed?
I've added the last object {"type": "object"} to display the intended behaviour - but in reality the last object will overrule the two defined objects ("enemy" and "friend") causing any kind of object to be valid with this schema. If I remove the last object, it will allow the two objects but nothing else.
JSON schema (using array for faster testing):
{
"type": "array",
"items": {
"anyOf": [
{"$ref": "#/definitions/friend"},
{"$ref": "#/definitions/enemy"},
{"$ref": "#/definitions/future"}
]
},
"definitions": {
"friend": {
"type": "object",
"properties": {
"time": {"type": "string"},
"value": {"type": "number", "minimum": 100}
},
"required": ["time", "value"],
"additionalProperties": false
},
"enemy": {
"type": "object",
"properties": {
"enemy": {"type": "string"},
"color": {"type": "number"}
},
"required": ["enemy", "color"],
"additionalProperties": false
},
"future": {
"type": "object",
"properties": {
"time": {"type": "string"}
}, "required": ["time"],
"additionalProperties": true
}
}
}
Example JSON (top 3 should be OK, last 3 should not be OK):
[
{"time": "123", "value": 100}, <- should be valid
{"time": "1212", "value": 150}, <- should be valid
{"enemy": "bla", "color": 123}, <- should be valid
{"time": "1212", "value": 50}, <- should be invalid bcoz of "future"
{"enemy": "bla", "color": "123"}, <- shouldn't be valid bcoz of "enemy" schema
{"somethingInFuture": 123, "someFutProp": "ok"} <- should be valid
]
It's not very clear what you really want but you probably want to use a combination of dependencies and minProperties here. The two forms of this keyword are used here: property dependency and schema dependency. You also want at least one property to be defined, hence minProperties. So you can do something like this (note that I also factorized the common schema for color; it may, or may not, be what you want):
{
"type": "object",
"minProperties": 1,
"additionalProperties": {
"type": "string" // All properties not explicitly defined are strings
},
"properties": {
"color": { "type": "number" }
},
"dependencies": {
"enemy": "color", // property dependency
"friend": { // schema dependency
"properties": { "color": { "minimum": 50 } },
"required": [ "color" ]
}
}
}
Note that this schema still allows "enemy" and "friend" at the same time (so does your original schema). To do better, sample JSONs you want to deem valid and invalid should be provided.

How to define JSON schema for object that holds Properties object?

I need to create a JSON schema for object that will include java Properties object as one of its properties.
The nested Properties object will be simply list of key=value. Both key and value are of type string.
I failed to find any docs that describe how to define the schema that includes 2 new types.
shall it be something like:
{
"type": "object",
"name": "MyObj",
"properties": {
"prop1": {
"type": "string",
"description": "prop1",
"required": true
},
"props": {
"type": "array",
"items": {
"type": "object"
"properties": {
"key": {
"type": "string",
"description": "key",
"required": true
},
"value": {
"type": "string",
"description": "the value",
"required": true
}
}
"description": "the value",
"required": true
}
}
}
}
The schema you have written (assuming the commas are fixed) describes data of the form:
{
"prop1": "Some string property goes here",
"props": [
{"key": "foo", "value": "bar"},
{"key": "foo2", "value": "bar2"},
...
]
}
If this is what you wanted, then you are already finished.
However, I do wonder why you are using key/value pairs in an array, when you could use a JSON object with string keys instead. Using the additionalProperties keyword, you could have a schema:
{
"type": "object",
"name": "MyObj",
"properties": {
"prop1": {
"type": "string",
"description": "prop1"
},
"props": {
"type": "object",
"additionalProperties": {
"type": "string",
"description": "string values"
}
}
}
}
This describes a data format like:
{
"prop1": "Some string property goes here",
"props": {
"foo": "bar",
"foo2": "bar2"
}
}
At W3 schools (JSON Syntax) you can read how the array should be defined.
There is no schema like the xsd for xml, however i've found an approach on json-schema.org. If you are able to, i'll advice to youse google-GSON library for JSON. You could Store key Value as "id" : "value" and build only one object, containing all requieed pairs:
{ "lang" : "EN" , "color" : "red" }
Your posted model is incorect, you can check it on jsonlint.com
Here is a working version, i'm not sure if the modell is as expected.
{
"type": "object",
"name": "MyObj",
"properties": [
{
"prop1": {
"type": "string",
"description": "prop1",
"required": true
},
"props": {
"type": "array",
"items": {
"type": "object",
"properties": {
"key": {
"type": "string",
"description": "key",
"required": true
},
"value": {
"type": "string",
"description": "the value",
"required": true
}
},
"description": "the value",
"required": true
}
}
}
]
}