I have a json response like below. In the views array may or may not contain actions array.
In the reponse If any of view array contains actions object , then i have to validate that actions data with json schema(schema1.json)
And in the schema i mentioned the action propertes like(type,label,localizedlabel) as required ones.
But when I modify key or value type of this type,label,localizedlabel in the response does not output any errors.
Tested via( https://www.jsonschemavalidator.net/). what wrong with my schema?
How can i validate actions object only whenever it present inside any of view array?
schema1.json
{
"$id": "",
"type": "array",
"items": {
"$id": "/items",
"type": "object",
"properties": {
"name": {
"$id": "/items/properties/name",
"type": "string",
"title": "The Name Schema ",
"default": "",
"examples": [
"Preview"
]
},
"displayOrder": {
"$id": "/items/properties/displayOrder",
"type": "integer",
"title": "The Displayorder Schema ",
"default": 0,
"examples": [
1
]
},
"actions": {
"$id": "/items/properties/actions",
"type": "array",
"items": {
"$id": "/items/properties/actions/items",
"type": "object",
"properties": {
"type": {
"$id": "/items/properties/actions/items/properties/type",
"type": "string",
"title": "The Type Schema ",
"default": "",
"examples": [
"watch"
]
},
"label": {
"$id": "/items/properties/actions/items/properties/label",
"type": "string",
"title": "The Label Schema ",
"default": "",
"examples": [
"Watch"
]
},
"localizedLabel": {
"$id": "/items/properties/actions/items/properties/localizedLabel",
"type": "object",
"properties": {
"ENG": {
"$id": "/items/properties/actions/items/properties/localizedLabel/properties/ENG",
"type": "string",
"title": "The Eng Schema ",
"default": "",
"examples": [
"Watch"
]
},
"ESP": {
"$id": "/items/properties/actions/items/properties/localizedLabel/properties/ESP",
"type": "string",
"title": "The Esp Schema ",
"default": "",
"examples": [
"Ver"
]
}
}
}
},
"required": [
"type",
"label",
"localizedLabel"
]
}
},
"localizedName": {
"$id": "/items/properties/localizedName",
"type": "object",
"properties": {
"ENG": {
"$id": "/items/properties/localizedName/properties/ENG",
"type": "string",
"title": "The Eng Schema ",
"default": "",
"examples": [
"Preview"
]
},
"ESP": {
"$id": "/items/properties/localizedName/properties/ESP",
"type": "string",
"title": "The Esp Schema ",
"default": "",
"examples": [
"Adelanto"
]
}
}
}
},
"required": [
"actions"
]
}
}
response json
[{
"season": 2017,
"teamData": {
"awayTeam": {
"id": 6,
"city": "Dallas",
"name": "Mavericks",
"abbr": "DAL",
"color": "#0B51A1"
},
"homeTeam": {
"id": 8,
"city": "Detroit",
"name": "Pistons",
"abbr": "DET",
"color": "#990300"
}
},
"views": [{
"name": "Preview",
"displayOrder": 1,
"groups": [{
"type": "static",
"displayOrder": 1,
"tiles": [{
"context": "event",
"collection": "event",
"auditType": "pregame-preview",
"displayOrder": 1,
"_id": "5ac58ea21ee2112b33291f1c",
"eventId": 2018040608,
"dimensions": {
"width": 372,
"height": 375
},
"tileId": "36b154e719d7d8397da487cbc4e5f7d1",
"renderTime": "2018-04-05T02:49:05+00:00",
"dataTime": "2018-04-05T02:48:58+00:00",
"dataStamp": 1522896538,
"location": "http://test.com/2018040608/static/pre-event/pregame-preview/1522896538.png",
"tile_type": "static"
}
]
}
],
"actions": [{
"type": "watch",
"label": "Watch",
"localizedLabel": {
"ENG": "Watch",
"ESP": "Ver"
}
}, {
"type": "record",
"label": "Record",
"localizedLabel": {
"ENG": "Record",
"ESP": "Grabar"
}
}, {
"type": "tile_overlay",
"label": "Current Standings",
"tili": {
"context": "event",
"collection": "event",
"auditType": "full-standings",
"_id": "5ac6f9de2ccaf768d092c918",
"eventId": 2018040608,
"dimensions": {
"width": 1140,
"height": 660
},
"tileId": "852f92537e68dc99b54f1228459ec9ef",
"renderTime": "2018-04-06T04:38:54+00:00",
"dataTime": "2018-04-06T04:38:52+00:00",
"dataStamp": 1522989532,
"location": "http://test.com/2018040608/static/pre-event/full-standings/1522989532.png"
},
"localizedLabel": {
"ENG": "Current Standings",
"ESP": "Posición actual"
}
}, {
"type": "favorite",
"label": "Favorite",
"localizedLabel": {
"ENG": "Favorite",
"ESP": "Favorito"
}
}
],
"localizedName": {
"ENG": "Preview",
"ESP": "Adelanto"
}
}, {
"name": "Team Stats",
"displayOrder": 2,
"groups": [{
"type": "static",
"displayOrder": 1,
"tiles": [{
"context": "event",
"collection": "event",
"auditType": "pregame-team_stats",
"displayOrder": 1,
"_id": "5ac6755a4f82eb58a5eae6a6",
"eventId": 2018040608,
"dimensions": {
"width": 372,
"height": 510
},
"tileId": "1302dc16c9fe68c3e6edadd98afce2bc",
"renderTime": "2018-04-05T19:13:30+00:00",
"dataTime": "2018-04-05T19:13:28+00:00",
"dataStamp": 1522955608,
"location": "http://test.com/2018040608/static/pre-event/pregame-team_stats/1522955608.png",
"tile_type": "static"
}
]
}
],
"localizedName": {
"ENG": "Team Stats",
"ESP": "Estadísticas del equipo"
}
}, {
"name": "Leaders",
"displayOrder": 3,
"groups": [{
"type": "static",
"displayOrder": 1,
"tiles": [{
"context": "event",
"collection": "event",
"auditType": "pregame-leaders",
"displayOrder": 1,
"_id": "5ac26eb31ee2112b3328b00c",
"eventId": 2018040608,
"dimensions": {
"width": 372,
"height": 510
},
"tileId": "96abc24c47d61327426ef2b24281acbf",
"renderTime": "2018-04-02T17:55:57+00:00",
"dataTime": "2018-04-02T17:55:54+00:00",
"dataStamp": 1522691754,
"location": "http://test.com/2018040608/static/pre-event/pregame-leaders/1522691754.png",
"tile_type": "static"
}
]
}
],
"localizedName": {
"ENG": "Leaders",
"ESP": "Líderes"
}
}
]
}
]
There's nothing wrong with your schema. It should do what you need if used properly. Because it only describes the "views" part of the schema you would need to iterate through your response and pass just the "views" part of each item to the validator one at a time.
Or, you could add enough of the response structure to the schema to validate everything at once. Then you could just pass your whole response to the validator.
{
"type": "array",
"items": {
"type": "object",
"properties": {
"views": { "$ref": "schema1.json" }
}
}
}
Related
Probably there are many question on JSON schema, however, I couldn't find an answer I was looking for.
I have a JSON message where the block inside FlagDetails array can come a max of 300 times. How do I restrict this using the schema which I have created below so that Time and UID can come max of 300 but max occurrences is 1 per array block.
JSON body:
{
"SData": {
"IData": {
"IDatas": {
"Flag": "Yes",
"FlagDetails": [
{
"Time": "2012-07-06 09:30:00",
"UID": 1234567
},
{
"Time": "2012-07-06 09:30:00",
"UID": 1234567
}
]
}
}
}
}
JSON schema:
{
"definitions": {},
"type": "object",
"required": [
"SData"
],
"properties": {
"SData": {
"title": "SData",
"type": "object",
"required": [
"IData"
],
"properties": {
"IData": {
"title": "IData",
"type": "object",
"required": [
"IDatas"
],
"properties": {
"IDatas": {
"title": "IDatas",
"type": "object",
"required": [
"Flag"
],
"properties": {
"Flag": {
"title": "Flag",
"type": "string",
"default": "",
"examples": [
"Yes"
],
"minLength": 2,
"maxLength": 3,
"minOccurs": 0,
"maxOccurs": 1,
"pattern": "^.*$"
},
"FlagDetails": {
"title": "FlagDetails",
"type": "array",
"default": [],
"items": {
"title": "Items",
"type": "object",
"properties": {
"Time": {
"title": "Time",
"type": "string",
"default": "",
"examples": [
"2012-07-06 09:30:00"
],
"minOccurs": 0,
"pattern": "^.*$"
},
"UID": {
"title": "UId",
"type": "integer",
"default": "",
"examples": [
"12345678912"
],
"minLength": 4,
"maxLength": 12,
"minOccurs": 0,
"pattern": "^.*$"
}
}
}
}
}
}
}
}
}
}
}
}
The answer to this is "minItems" & "maxItems". I have used those and it works perfectly.
"FlagDetails": {
"title": "FlagDetails",
"type": "array",
**"minItems": 0,
"maxItems": 300,**
"default": []
I am trying to add a dependency to a property based on the property value before it. Within my JSON, there is an instances property. If that property is > 2 only then show the StartIndex property. I have tried adding another if-then-else to my pre-existing one (wrapped in an allOf) but that was failing so I decided to take the dependency route.
Here's the JSON Schema with my attempt at adding the dependency withing the StartIndex property:
{
"definitions": {},
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "http://example.com/root.json",
"type": "object",
"title": " ",
"required": [
"NetworkProfile",
"GroupEmailAddress",
"FILESTORAGE",
"Memory",
"Instances",
"StartIndex"
],
"properties": {
"Name": {
"$id": "#/properties/Name",
"type": "string",
"title": "Name",
"default": "",
"description": "The first five characters are generated per specs. Specify the next eight characters here and we suggest: Data Center (2), Layer (2-3), Sequential Number (2).",
"examples": [
""
],
"minLength": 0,
"maxLength": 8,
"pattern": "^[a-zA-Z0-9]*$",
"validationMessages": {
"pattern": "Must contain only alphanumeric characters.",
"required": "Must contain only alphanumeric characters."
}
},
"Instances": {
"$id": "#/properties/Instances",
"default": 2,
"examples": [
"2"
],
"pattern": "^(.*)$",
"title": "Number of VM Node",
"description": "Number of VM instance in this request",
"minimum": 1,
"maximum": 5,
"type": "number"
},
"StartIndex": {
"dependencies": {
"Instances": {
"minimum": 2
}
},
"$id": "#/properties/StartIndex",
"default": 1,
"examples": [
"1"
],
"pattern": "^(.*)$",
"title": "Start Index for these VMs",
"description": "The starting sequence number for this set of servers",
"type": "number",
"minimum": 1
},
"Memory": {
"$id": "#/properties/Memory",
"type": "number",
"enum": [
4,
8,
16
],
"title": "RAM (GB)",
"default": 4,
"examples": [
""
],
"pattern": "^(.*)$"
},
"GroupEmailAddress": {
"$id": "#/properties/GroupEmailAddress",
"type": "string",
"title": "Group Email Address",
"default": "",
"description": "This should be an email address for your application group. Security will use this email address to contact when TLS cert needs to be renewed.",
"examples": [
""
]
},
"User": {
"$id": "#/properties/User",
"type": "string",
"title": "Admin Group",
"default": "",
"examples": [
""
],
"description": "The user account that will have access to the vm. Default belong to requester if not specified. Additional users can be added by using a comma(,) as a separator. <br> (e.g. Americas\\firstName_lastName). Only PAC group is accepted for PROD.",
"pattern": "^((Americas|Asia-Pacific|Europe)\\\\.[a-zA-Z0-9_.%]*[*,]?[\\s]*)*$"
},
"NetworkProfile": {
"$id": "#/properties/NetworkProfile",
"type": "string",
"enum": [
"APP",
"WEB"
],
"title": "Server Type/Function",
"description": "Web Server is meant to serve static pages e.g. HTML and CSS, while Application Server is responsible for generating dynamic content by executing server side code.",
"default": "",
"examples": [
""
],
"pattern": "^(.*)$"
},
"eDell": {
"$id": "#/properties/eDell",
"title": "Is the VM related to eDell? ",
"type": "boolean",
"default": false
},
"Disks": {
"$id": "#/properties/Disks",
"type": "array",
"title": "Local (Non-OS) Storage. Default OS Drive (C) size is 60GB. The (D) drive is fixed at 20 GB, can use E-Z for additional storage. Can only add an additional 900GB.",
"items": {
"$id": "#/properties/Disks/items",
"type": "object",
"title": " ",
"required": [
"data"
],
"properties": {
"data": {
"$id": "#/properties/Disks/items/properties/data",
"type": "object",
"title": " ",
"required": [
"capacity",
"initial_location"
],
"properties": {
"capacity": {
"$id": "#/properties/Disks/items/properties/data/properties/capacity",
"type": "number",
"title": "Capacity (GB)",
"default": "",
"examples": [
"20"
],
"minimum": 5,
"maximum": 900
},
"initial_location": {
"$id": "#/properties/Disks/items/properties/data/properties/initial_location",
"type": "string",
"title": "Drive Letter",
"default": "E",
"examples": [
"/u02"
],
"description": "Drive Letter of the partition without colon",
"pattern": "^[eE,fF,gG,hH,iI,jJ,kK,lL,mM,nN,oO,pP,qQ,rR,sS,tT,uU,vV,wW,xX,yY,zZ]{1}$",
"validationMessages": {
"pattern": "C,D are reserved use E-Z.",
"required": "C,D are reserved use E-Z."
}
}
}
}
}
}
},
"FILESTORAGE": {
"$id": "#/FileStorage",
"type": "string",
"enum": [
"YES",
"NO"
],
"title": "Add File Storage",
"default": "NO",
"examples": [
""
],
"pattern": "^(.*)$"
}
},
"if": {
"properties": {
"FILESTORAGE": {
"const": "YES"
}
}
},
"then": {
"properties": {
"NASDisk": {
"$id": "#/properties/NASDisk",
"type": "object",
"title": "File Storage",
"required": [
"AppName",
"SizeGB",
"Protocol",
"ShareOwner",
"Function"
],
"properties": {
"Protocol": {
"$id": "#/properties/NASDisk/properties/Protocol",
"type": "string",
"default": "CIFS",
"options": {
"hidden": "true"
}
},
"Function": {
"$id": "#/properties/NASDisks/properties/Function",
"type": "string",
"enum": [
"File",
"Storage",
"Backup",
"App",
"Log",
"Database",
"Repository"
],
"title": "Choose Function for NAS",
"default": "File",
"examples": [
""
],
"pattern": "^(.*)$"
},
"AppName": {
"$id": "#/properties/NASDisk/properties/AppName",
"type": "string",
"title": "App Name",
"default": "",
"description": "Abbreviation or alias of the application name to be prefix to the share name, limit to 10 letters",
"pattern": "^[a-zA-Z]{1,10}$"
},
"SizeGB": {
"$id": "#/properties/NASDisk/properties/SizeGB",
"type": "number",
"title": "Size (GB)",
"default": 5,
"examples": [
5
],
"minimum": 5,
"maximum": 500
},
"ShareOwner": {
"$id": "#/properties/NASDisk/properties/ShareOwner",
"type": "string",
"title": "Share Owner",
"default": "",
"description": "User account with ownership of the share. Group ownership can be specified using the format DOMAIN\\UserName. <br> (e.g. Americas\\firstName_lastName).",
"examples": [
"adms_c_lawlor"
],
"pattern": "^((Americas|Asia-Pacific|Europe)\\\\.[a-zA-Z0-9_.%]*[*,]?[\\s]*)*$"
},
"FC_Members": {
"$id": "#/properties/NASDisk/properties/FC_Members",
"type": "string",
"description": "Comma separated AD groups that will have full control of share."
},
"RW_Members": {
"$id": "#/properties/NASDisk/properties/RW_Members",
"type": "string",
"description": "Comma separated AD groups that will have read/write control of share."
}
}
}
}
},
"else": {}
}
Here was my allOf attempt:
"allOf": [
{
"if": {
"properties": {
"FILESTORAGE": {
"const": "YES"
}
}
},
"then": {
"properties": {
"NASDisk": {
"$id": "#/properties/NASDisk",
"type": "object",
"title": "File Storage",
"required": [
"AppName",
"SizeGB",
"Protocol",
"ShareOwner",
"Function"
],
"properties": {
"Protocol": {
"$id": "#/properties/NASDisk/properties/Protocol",
"type": "string",
"default": "CIFS",
"options": {
"hidden": "true"
}
},
"Function": {
"$id": "#/properties/NASDisks/properties/Function",
"type": "string",
"enum": [
"File",
"Storage",
"Backup",
"App",
"Log",
"Database",
"Repository"
],
"title": "Choose Function for NAS",
"default": "File",
"examples": [
""
],
"pattern": "^(.*)$"
},
"AppName": {
"$id": "#/properties/NASDisk/properties/AppName",
"type": "string",
"title": "App Name",
"default": "",
"description": "Abbreviation or alias of the application name to be prefix to the share name, limit to 10 letters",
"pattern": "^[a-zA-Z]{1,10}$"
},
"SizeGB": {
"$id": "#/properties/NASDisk/properties/SizeGB",
"type": "number",
"title": "Size (GB)",
"default": 5,
"examples": [
5
],
"minimum": 5,
"maximum": 500
},
"ShareOwner": {
"$id": "#/properties/NASDisk/properties/ShareOwner",
"type": "string",
"title": "Share Owner",
"default": "",
"description": "User account with ownership of the share. Group ownership can be specified using the format DOMAIN\\UserName. <br> (e.g. Americas\\firstName_lastName).",
"examples": [
"adms_c_lawlor"
],
"pattern": "^((Americas|Asia-Pacific|Europe)\\\\.[a-zA-Z0-9_.%]*[*,]?[\\s]*)*$"
},
"FC_Members": {
"$id": "#/properties/NASDisk/properties/FC_Members",
"type": "string",
"description": "Comma separated AD groups that will have full control of share."
},
"RW_Members": {
"$id": "#/properties/NASDisk/properties/RW_Members",
"type": "string",
"description": "Comma separated AD groups that will have read/write control of share."
}
}
}
}
},
"else": {
}
},
{
"if": {
"properties": {
"Instances": {
"minimum": "1"
}
}
},
"then": {
"properties": {
"StartIndex": {
"$id": "#/properties/StartIndex",
"hidden": true,
"default": "1",
"examples": [
"1"
],
"pattern": "^(.*)$",
"title": "Start Index for these VMs",
"description": "The starting sequence number for this set of servers",
"type": "number",
"minimum": 0
}
}
},
"else": {
"properties": {
"StartIndex": {
"$id": "#/properties/StartIndex",
"default": "",
"examples": [
"1"
],
"pattern": "^(.*)$",
"title": "Start Index for these VMs",
"description": "The starting sequence number for this set of servers",
"type": "number",
"minimum": 0
}
}
}
}
]
UPDATE: So I actually figure this out using nested properties as shown here
"isMultiDropdown": {
"title": "",
"$id": "#/properties/isMultiDropdown",
"required": [
"isMulti"
],
"type": "object",
"if": {
"properties": {
"isMulti": {
"const": "YES"
}
}
},
"then": {
"properties": {
"StartIndex": {
"$id": "#/properties/StartIndex",
"default": "",
"examples": [
"1"
],
"pattern": "^(.*)$",
"title": "Start Index for these VMs",
"description": "The starting sequence number for this set of servers",
"type": "number",
"minimum": 0
}
}
},
"properties": {
"isMulti": {
"$id": "#/properties/isMultiDropdown/isMulti",
"enum": [
"YES",
"NO"
],
"title": "Are you provisioning multiple instances?",
"default": "NO",
"examples": [
""
],
"pattern": "^(.*)$",
"type": "string"
}
}
}
```
I have a Json request having the below data and a corresponding json schema for it
With this request, I want to make a few fields as required depending on the mode
Say if mode is 1, then I want the fields a and b in obj1 to be required and field x in obj3 as required.
Now if the mode is 2, I would want fields p, q and r in obj2 to be required, fields a and c in obj1 as required and field y in obj3 as required.
Next if the mode is 3, I want only fields a and c as required
Json request
{
"mode": "1",
"obj1": {
"a": 12,
"b": "test",
"c": "18 June 2019"
},
"obj2": {
"p": 100,
"q": "new",
"r": "19 June 2019",
"s" : "test2"
},
"obj3": {
"x": 12,
"y": "test3"
}
}
**Json schema**
{
"definitions": {},
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "http://example.com/root.json",
"type": "object",
"properties": {
"mode": {
"$id": "#/properties/mode",
"type": "string",
"examples": [
"1"
]
},
"obj1": {
"$id": "#/properties/obj1",
"type": "object",
"title": "The Obj 1 Schema",
"properties": {
"a": {
"$id": "#/properties/obj1/properties/a",
"type": "integer",
"examples": [
12
]
},
"b": {
"$id": "#/properties/obj1/properties/b",
"type": "string",
"examples": [
"test"
]
},
"c": {
"$id": "#/properties/obj1/properties/c",
"type": "string",
"examples": [
"18 June 2019"
]
}
}
},
"obj 2": {
"$id": "#/properties/obj2",
"type": "object",
"title": "The Obj 2 Schema",
"properties": {
"p": {
"$id": "#/properties/obj2/properties/p",
"type": "integer",
"examples": [
100
]
},
"q": {
"$id": "#/properties/obj2/properties/q",
"type": "string",
"examples": [
"new"
]
},
"r": {
"$id": "#/properties/obj2/properties/r",
"type": "string",
"examples": [
"19 June 2019"
]
},
"s": {
"$id": "#/properties/obj2/properties/s",
"type": "string",
"examples": [
"test2"
]
}
}
},
"obj 3": {
"$id": "#/properties/obj3",
"type": "object",
"title": "The Obj 3 Schema",
"properties": {
"x": {
"$id": "#/properties/obj3/properties/x",
"type": "integer",
"examples": [
12
]
},
"y": {
"$id": "#/properties/obj3/properties/y",
"type": "string",
"examples": [
"test3"
]
}
}
}
}
}
EDIT - Changed the schema to validate based on the suggestion by #gregsdennis
JSON SCHEMA
{
"definitions": {},
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "http://example.com/root.json",
"type": "object",
"properties": {
"mode": {
"$id": "#/properties/mode",
"type": "string",
"examples": [
"1"
]
},
"obj1": {
"$id": "#/properties/obj1",
"type": "object",
"title": "The Obj 1 Schema",
"properties": {
"a": {
"type": "integer",
"examples": [
12
]
},
"b": {
"type": "string",
"examples": [
"test"
]
},
"c": {
"type": "string",
"examples": [
"18 June 2019"
]
}
}
},
"obj 2": {
"$id": "#/properties/obj2",
"type": "object",
"title": "The Obj 2 Schema",
"properties": {
"p": {
"type": "integer",
"examples": [
100
]
},
"q": {
"type": "string",
"examples": [
"new"
]
},
"r": {
"type": "string",
"examples": [
"19 June 2019"
]
},
"s": {
"type": "string",
"examples": [
"test2"
]
}
}
},
"obj 3": {
"$id": "#/properties/obj3",
"type": "object",
"title": "The Obj 3 Schema",
"properties": {
"x": {
"type": "integer",
"examples": [
12
]
},
"y": {
"type": "string",
"examples": [
"test3"
]
}
}
}
},
"oneOf": [
{
"properties": {
"mode": {"const": 1},
"obj1": {"required": ["a","b"]},
"obj3": {"required": ["x"]}
}
},
{
"properties": {
"mode": {"const": 2},
"obj2": {"required": ["p","q","r"]},
"obj1": {"required": ["a","c"]},
"obj3": {"required": ["y"]}
}
}
]
}
So, in brief, irrespective of how many modes, fields or objects I have, I would like only a few selected fields from different objects to be required at a given time for a particular mode.
Can anyone please suggest any solutions to achieve this? Is it possible to have such validations in the json schema?
What you want is an oneOf where each subschema gives a valid state for each of obj* properties. Each state would be something like this:
{
"properties": {
"mode": {"const": 1},
"obj1": {"required": ["a","b"]},
"obj3": {"required": ["x"]}
}
}
Create one of these for each of the states you listed in your question, and throw them all in a oneOf that lives at the root.
You could do this with if/then/else, but for this case, I'd prefer the oneOf to avoid nesting.
Also, I notice that you have a lot of superfluous $ids in the middle that are just specifying their location within the schema. You want the one at the root, but you don't need the others. Implementations can work out these kinds of location-based references trivially.
Using Draft-07
What I got was
valid JSON
What error I expected from audit object was
directory: String length must be greater than or equal to 2
Tried two different validators with same results
https://www.jsonschemavalidator.net/
GoLang https://github.com/xeipuuv/gojsonschema
This is my schema
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "ISAM-Wrapper",
"description": "Validate isam wrapper json",
"type": "object",
"properties": {
"directory": {
"description": "path to location of isam file",
"type": "string",
"minLength": 2
},
"isamFile": {
"description": "isam database file",
"type": "string",
"minLength": 4
},
"isamIndex": {
"description": "isam index file",
"type": "string",
"minLength": 4
},
"port": {
"description": "port number for REST listener",
"type": "integer",
"minimum": 60410,
"maximum": 69999
},
"actions": {
"description": "Which operations are supported",
"type": "object",
"items": {
"properties": {
"create": {
"type": "boolean"
},
"read": {
"type": "boolean"
},
"update": {
"type": "boolean"
},
"delete": {
"type": "boolean"
}
}
},
"required": [
"create",
"read",
"update",
"delete"
]
},
"fields": {
"description": "each object describes one field of the isam file",
"type": "array",
"minItems": 1,
"items": {
"title": "field",
"description": "field schema",
"type": "object",
"properties": {
"name": {
"type": "string",
"minLength": 1
},
"ordinal": {
"type": "integer",
"minimum": 0
},
"offset": {
"type": "integer",
"minimum": 0
},
"length": {
"type": "integer",
"minimum": 1
},
"dataType": {
"enum": [
"uchar",
"ulong",
"long",
"uint",
"int",
"ushort",
"short"
]
}
},
"required": [
"name",
"ordinal",
"offset",
"length",
"dataType"
]
}
},
"audit": {
"description": "input needed to enable and configure isam auditing",
"type": "object",
"items": {
"properties": {
"enable": {
"enum": [
true,
false
]
},
"directory": {
"type": "string",
"minLength": 2
},
"fileName": {
"type": "string",
"minLength": 4
},
"workDirectory": {
"type": "string",
"minLength": 2
},
"archiveDirectory": {
"type": "string",
"minLength": 2
},
"interval": {
"type": "integer",
"minimum": 1
},
"byteThreshold": {
"type": "integer",
"minimum": 1048576,
"maximum": 1073741824
}
}
},
"required": [
"enable"
],
"if": {
"not": {
"properties": {
"enable": {
"enum": [
false
]
}
}
}
},
"then": {
"required": [
"directory",
"fileName",
"workDirectory",
"archiveDirectory",
"interval",
"byteThreshold"
]
}
}
},
"required": [
"directory",
"isamFile",
"isamIndex",
"port",
"actions",
"fields",
"audit"
]
}
This is my JSON
{
"directory": "./",
"isamFile": "isam.dat",
"isamIndex": "isam.idx",
"port": 60410,
"actions": {
"create": true,
"read": true,
"update": true,
"delete": true
},
"fields": [
{
"name": "F1",
"ordinal": 0,
"offset": 0,
"length": 4,
"dataType": "ulong"
},
{
"name": "F2",
"ordinal": 1,
"offset": 4,
"length": 4,
"dataType": "ulong"
}
],
"audit": {
"enable": true,
"directory": "",
"fileName": "file",
"workDirectory": "./work",
"archiveDirectory": "./archive",
"interval": 5,
"byteThreshold": 1500000
}
}
This issue you have is that your schema is invalid. For both actions and audit you specify these as objects but you don't provide any properties. What you do do, however, is specify an items key (which does nothing here - that's a key on an array) which contains the properties.
Once you correct this error, the schema behaves as you intend, see https://repl.it/repls/BlankWellmadeFrontpage
I'm just starting with Swagger UI and I'm trying to understand how it works.
So far I've entered some JSON (manually) and this is the result:
{
"swagger": "2.0",
"info": {
"version": "1.0.0",
"title": "PhakeApps API",
"contact": {
"name": "PhakeApps API team",
"url": "http://phakeapps.com/"
},
"license": {
"name": "Creative Commons 4.0 International",
"url": "http://creativecommons.org/licenses/by/4.0/"
}
},
"host": "api.phakeapps.com",
"basePath": "/v1",
"schemes": [
"http"
],
"produces": [
"application/json"
],
"consumes": [
"application/json"
],
"paths": {
"/places/search": {
"post": {
"tags": [
"Places"
],
"description": "Search for (a) place(s) <br /><br /> <b>id</b> - The ID of the request. <br /> <b>api_key</b> - API Key for the platform the request is sent. <i>Currently, not required.</i> <br /> <b>Params</b> - Required. <i>See model & model schema.</i>",
"operationId": "PlacesSearch",
"produces": [
"application/json"
],
"consumes": [
"application/json"
],
"parameters": [
{
"name": "request",
"in": "body",
"paramType": "body",
"description": "Object containing the <u>id</u>, <u>api_key</u> and certain <u>params</u>.",
"required": true,
"schema": {
"$ref": "#/definitions/Search"
}
}
],
"responses": {
"200": {
"description": "Success",
"schema": {
"$ref": "#/definitions/PlacesResult"
}
},
"403": {
"description": "Validation error or Server Failure",
"schema": {
"$ref": "#/definitions/Error"
}
}
}
}
}
},
"definitions": {
"PlacesResult": {
"required": [
"data",
"id",
"code"
],
"properties": {
"data": {
"$ref": "#/definitions/Places"
},
"id": {
"type": "integer",
"format": "int32"
},
"code": {
"type": "integer",
"format": "int32"
}
}
},
"Places": {
"required": [
"places"
],
"properties": {
"places": {
"$ref": "#/definitions/Place"
}
}
},
"City": {
"required": [
"id",
"name"
],
"properties": {
"id": {
"type": "string"
},
"name": {
"type": "string"
}
}
},
"Neighbourhood": {
"required": [
"id",
"name"
],
"properties": {
"id": {
"type": "string"
},
"name": {
"type": "string"
}
}
},
"Cuisine": {
"required": [
"id",
"name"
],
"properties": {
"id": {
"type": "string"
},
"name": {
"type": "string"
}
}
},
"Place": {
"required": [
"id",
"name",
"city",
"neighbourhood",
"address",
"cuisine",
"price",
"photos_cnt",
"lat",
"lng",
"is_fav"
],
"properties": {
"id": {
"type": "string"
},
"name": {
"type": "string"
},
"city": {
"type": "array",
"items": {
"$ref": "#/definitions/City"
}
},
"neighbourhood": {
"type": "array",
"items": {
"$ref": "#/definitions/Neighbourhood"
}
},
"address": {
"type": "string"
},
"cuisine": {
"type": "array",
"items": {
"$ref": "#/definitions/Cuisine"
}
},
"price": {
"type": "integer",
"format": "int32"
},
"photos_cnt": {
"type": "integer",
"format": "int32"
},
"lat": {
"type": "double"
},
"lng": {
"type": "double"
},
"is_fav": {
"type": "boolean"
}
}
},
"Search": {
"required": [
"id",
"api_key",
"params"
],
"properties": {
"id": {
"type": "integer",
"format": "int64"
},
"api_key": {
"type": "string"
},
"params": {
"$ref": "#/definitions/SearchParams"
}
}
},
"SearchParams": {
"required": [
"user_id",
"city_id",
"people",
"dt",
"locale"
],
"properties": {
"user_id": {
"type": "string",
"default": "956dda4c21c72e48f5f17a7cd783a0f7"
},
"city_id": {
"type": "string",
"default": "4ec4b3e6098c9d23c925b0c2451eb06a"
},
"people": {
"type": "integer",
"format": "int32",
"minimum": 1,
"default": 2
},
"dt": {
"type": "integer",
"format": "int32",
"default": "1427742000"
},
"locale": {
"type": "string",
"default": "bg"
},
"place_id": {
"type": "string",
"default": "0"
},
"neighborhood_id": {
"type": "string",
"default": "0"
},
"cuisine_id": {
"type": "string",
"default": "0"
},
"kids_place": {
"type": "boolean",
"default": false
},
"price": {
"type": "integer",
"format": "int64",
"default": 1
},
"outdoors": {
"type": "boolean",
"default": false
}
}
},
"Error": {
"required": [
"code",
"data"
],
"properties": {
"code": {
"type": "integer",
"format": "int32"
},
"data": {
"type": "array",
"items": {
"type": "array"
}
}
}
}
}
}
However, swagger's validator says it's not valid. The error I get is this
[
{
"level": "error",
"domain": "validation",
"keyword": "anyOf",
"message": "instance failed to match at least one required schema among 2",
"schema": {
"loadingURI": "http://json-schema.org/draft-04/schema#",
"pointer": "/properties/type"
},
"instance": {
"pointer": "/definitions/Place/properties/lat/type"
}
}
]
Note that it works as expected (so far). It displays the data (models and models' structure) properly. Make requests and retrieves responses. Yet the validator says it's not valid. (The yellow badge saying 'Invalid', not the red one that says 'Error').
What am I missing?
Your spec is indeed not valid. In your Place definition, you use "type": "double" to describe the type of the lat (and also lng) property, but such a type does not exist.
If you want to describe a numeric value of 'double' size, you should change the definition as follows:
"lng": {
"type": "number",
"format": "double"
}
Do that everywhere you use the double type, and it should resolve that issue.