I have been trying to fix an error where the Swagger would not render my JSON response - here is an attached picture of it.
The console does not show any errors so I am struggling to allocate from where the issue could be coming - here is the console result.
I would be extremely thankful if someone could suggest a way to fix that problem.
Here is my code:
"paths": {
"/unit/{jobs}": {
"get": {
"tags": [
"Services"
],
"summary": "Jobs information",
"description": "Returns JSON with content of jobs details.",
"operationId": "unitJobs",
"security": [
{
"Application": []
},
{
"Profile": []
},
{
"Authorization": []
}
],
"parameters": [
{
"name": "jobs",
"in": "path",
"required": true,
"schema": {
"type": "string"
},
"description": "Jobs"
}
],
"responses": {
"200": {
"description": "Success!",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Job"
}
}
}
}
}
}
}
},
"components": {
"securitySchemes": {
"Application": {
"name": "X-Application",
"type": "apiKey",
"in": "header"
},
"Profile": {
"name": "X-Profile",
"type": "apiKey",
"in": "header"
},
"Authorization": {
"type": "http",
"scheme": "bearer"
}
},
"schemas": {
"Job": {
"properties": {
"id": {
"type": "integer",
"example": 2584075,
"description": "Unique identifier"
},
"currency_code": {
"type": "string",
"example": "GBP",
"description": "Currency code"
},
"payment_method": {
"type": "array"
},
"app_time": {
"type": "integer",
"example": 1504620000,
"description": "Appointment time for the job in UTC timestamp"
},
"flexible_from": {
"type": "integer",
"example": null,
"description": "Start of timeframe to execute the job in UTC timestamp"
},
"flexible_to": {
"type": "integer",
"example": null,
"description": "End of timeframe to execute the job in UTC timestamp"
},
"insufficient_travel_time_warning_time": {
"type": "integer",
"example": "1504616400",
"description": "Time up until Pro should leave previous job in order to get to this job in time in UTC timestamp"
},
"total_formatted": {
"type": "string",
"example": "£97",
"description": "Price of the service after discounts"
},
"base_total_formatted": {
"type": "string",
"example": "£97",
"description": "Price of the service before discounts"
},
"price_notes": {
"type": "array",
"example": [
"Credit applied",
"Compensation included"
],
"description": "Description notes for the price of the services."
},
"require_summary": {
"type": "integer",
"example": 4,
"description": "\n * `0` - No summary required \n * `1` - Should send summary at the end of the day \n * `2` - Should send summary now \n * `3` - Can’t proceed until summary sent \n * `4` - Summary sent"
},
"work_time": {
"type": "integer",
"example": 120,
"description": "Job duration in minutes"
},
"valid_to": {
"type": "integer",
"example": "1504620000",
"description": "Time after which job is no more valid and has to be updated in UTC timestamp"
},
"attachments.origin_key": {
"type": "string",
"example": "checklist",
"description": "\n Identifies where the attachment is coming from: \n * `checklist` - from answering a question that requires attachment \n * `job` - from job screen \n * `configurator` - from booking process when filling a choice item of type attachment"
},
"services_price_modifiers": {
"type": "array",
"example": ""
},
"reference_number": {
"type": "string",
"example": "20082602SYS",
"description": "Unique identifying number for each job"
},
"purchase_order_number": {
"type": "string",
"example": "12-13-14-15-16",
"description": "Unique number assigned to a purchase order form"
},
"contacts": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Contact"
}
},
"message_templates": {
"type": "array",
"items": {
"$ref": "#/components/schemas/MessageTemplate"
}
},
"decline_reason_groups": {
"type": "array",
"items": {
"$ref": "#/components/schemas/DeclineReasonGroup"
}
},
"icons": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Icon"
}
}
}
},
"Contact": {
"properties": {
"id": {
"type": "integer",
"example": 203,
"description": "Unique identifier"
},
"value": {
"type": "string",
"example": "02034042956",
"description": "Contact number"
},
"type": {
"$ref": "#/components/schemas/ContactType"
},
"description": {
"type": "string",
"example": "Customer Service",
"description": "Name of the corresponding department"
},
"display_positions": {
"type": "array",
"example": [
2,
3,
7
],
"description": ""
}
}
},
"MessageTemplate": {
"properties": {
"id": {
"type": "integer",
"example": 15,
"description": "Unique identifier"
},
"title": {
"type": "string",
"example": "In front of the property",
"description": "Template message title"
},
"message": {
"type": "string",
"example": "Dear [CLIENT_NAME], I am in front of your property. Please let me in or call our office on 02034041930. Your Fantastic Professional",
"description": "The containing text of the message"
},
"vars": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Var"
},
},
"destination_option_title": {
"type": "string",
"example": "to office",
"description": "Optionally defines the destination of the title"
}
}
},
"DeclineReasonGroup": {
"properties": {
"title": {
"type": "string",
"example": "Technical issues",
"description": "Decline reason title"
},
"sort": {
"type": "integer",
"example": 100,
"description": ""
},
"decline_reasons": {
"type": "array",
"items": {
"$ref": "#/components/schemas/DeclineReason"
}
}
}
},
"Icon": {
"properties": {
"name": {
"type": "string",
"example": "Key:",
"description": "The name of the icon"
},
"note": {
"type": "string",
"example": "Yes",
"description": "Addiditonal information about the icon"
}
}
},
"Var": {
"properties": {
"variable": {
"type": "string",
"example": "CLIENT_NAME",
"description": "Different client details"
},
"type": {
"$ref": "#/components/schemas/VarType"
},
"field": {
"type": "string",
"example": "clientName",
"description": "Fields where the client's information is filled"
}
}
},
"DeclineReason": {
"properties": {
"id": {
"type": "integer",
"example": 11,
"description": "Unique identifier"
},
"name": {
"type": "string",
"example": "Car is broken",
"description": "The name of a decline reason"
},
"requires_comment": {
"type": "boolean",
"example": true,
"description": "Determines whether the comment section is required to be filled "
},
"success_message": {
"type": "string",
"example": "Please contact Stanimir Tomov on 07472761402 - he can find you another.",
"description": "The message which pops up after the request made is successful"
},
"sort": {
"type": "integer",
"example": 100,
"description": ""
}
}
},
"ContactType": {
"type": "integer",
"enum": [
1,
2,
3,
4
],
"description": "* `1` - Customer Service \n * `2` - Sales \n * `3` - Finance \n * `4` - Other"
},
"VarType": {
"type": "string",
"enum": [
"auto",
"manual"
],
"description": "* `auto` - information being filled automatically \n * `manual` - information being filled manually "
}
}
}
}
The problem is not the responses them selves, rather it is the definition of the 'payment_method' in the Job schema:
You need to define the items in an array definition, try this:
"payment_method": {
"type": "array",
"items": {
"type": "string"
}
}
Related
The full error is below.
New-AzResourceGroupDeployment : 23:35:36 - Error: Code=InvalidTemplate; Message=Deployment template validation failed: 'The template reference 'ion5eddb999' is ambiguous: there are multiple template
resources '/subscriptions/d2143d4c-a258-4a38-8fbf-de0e42756e22/resourceGroups/sumantest/providers/Microsoft.Compute/virtualMachines/ion5eddb999,/subscriptions/d2143d4c-a258-4a38-8fbf-de0e42756e22/resou
rceGroups/sumantest/providers/Microsoft.SqlVirtualMachine/SqlVirtualMachines/ion5eddb999' defined with this name. Please use fully qualified resource identity instead. Please see
https://aka.ms/arm-template-expressions/#reference for usage details.'.
Below is the ARM template. I have tried using hard coded sqlserver name as well, but same error.
Please let me know what is wrong I am doing here. Any help is appreciated.
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"virtualMachineName": {
"type": "String",
"defaultValue": "ion5eddb999",
"metadata": {
"description": "The name of the VM"
}
},
"virtualMachineSize": {
"type": "String",
"defaultValue": "Standard_B4ms",
"metadata": {
"description": "The virtual machine size."
}
},
"ipAddress":{
"type":"string",
"defaultValue": "172.31.172.99",
"metadata": {
"description": "The virtual machine ip address"
}
},
"existingVirtualNetworkName": {
"type": "String",
"defaultValue": "ion5ed-vnet",
"metadata": {
"description": "Specify the name of an existing VNet in the same resource group"
}
},
"existingVnetResourceGroup": {
"type": "String",
"defaultValue": "ion5ed-gateway",
"metadata": {
"description": "Specify the resrouce group of the existing VNet"
}
},
"existingSubnetName": {
"type": "String",
"defaultValue": "ion5ed-sub-devtest",
"metadata": {
"description": "Specify the name of the Subnet Name"
}
},
"imageOffer": {
"type": "String",
"defaultValue": "sql2019-ws2019",
"allowedValues": [
"sql2019-ws2019",
"sql2017-ws2019",
"SQL2017-WS2016",
"SQL2016SP1-WS2016",
"SQL2016SP2-WS2016",
"SQL2014SP3-WS2012R2",
"SQL2014SP2-WS2012R2"
],
"metadata": {
"description": "Windows Server and SQL Offer"
}
},
"sqlSku": {
"type": "String",
"defaultValue": "Standard",
"allowedValues": [
"Standard",
"Enterprise",
"SQLDEV",
"Web",
"Express"
],
"metadata": {
"description": "SQL Server Sku"
}
},
"adminUsername": {
"type": "String",
"metadata": {
"description": "The admin user name of the VM"
}
},
"adminPassword": {
"type": "SecureString",
"metadata": {
"description": "The admin password of the VM"
}
},
"storageWorkloadType": {
"type": "String",
"defaultValue": "General",
"allowedValues": [
"General",
"OLTP",
"DW"
],
"metadata": {
"description": "SQL Server Workload Type"
}
},
"sqlVirtualMachineName": {
"type": "string",
"defaultValue": "ion5eddb999"
},
"sqlDataDisksCount": {
"type": "int",
"defaultValue": 1,
"minValue": 1,
"maxValue": 8,
"metadata": {
"description": "Amount of data disks (1TB each) for SQL Data files"
}
},
"dataPath": {
"type": "String",
"defaultValue": "F:\\SQLData",
"metadata": {
"description": "Path for SQL Data files. Please choose drive letter from F to Z, and other drives from A to E are reserved for system"
}
},
"sqlLogDisksCount": {
"type": "int",
"defaultValue": 1,
"minValue": 1,
"maxValue": 8,
"metadata": {
"description": "Amount of data disks (1TB each) for SQL Log files"
}
},
"logPath": {
"type": "String",
"defaultValue": "G:\\SQLLog",
"metadata": {
"description": "Path for SQL Log files. Please choose drive letter from F to Z and different than the one used for SQL data. Drive letter from A to E are reserved for system"
}
},
"location": {
"type": "string",
"defaultValue": "[resourceGroup().location]",
"metadata": {
"description": "Location for all resources."
}
}
},
"variables": {
"networkInterfaceName": "[concat(parameters('virtualMachineName'), '-nic')]",
//"networkSecurityGroupName": "[concat(parameters('virtualMachineName'), '-nsg')]",
"diskConfigurationType": "NEW",
"subnetRef": "[resourceID(parameters('existingVNetResourceGroup'), 'Microsoft.Network/virtualNetWorks/subnets', parameters('existingVirtualNetworkName'), parameters('existingSubNetName'))]",
"dataDisksLuns": "[array(range(0 ,parameters('sqlDataDisksCount')))]",
"logDisksLuns": "[array(range(parameters('sqlDataDisksCount'), parameters('sqlLogDisksCount')))]",
"dataDisks": {
"createOption": "empty",
"caching": "ReadOnly",
"writeAcceleratorEnabled": false,
"storageAccountType": "StandardSSD_LRS",
"diskSizeGB": 100
},
"tempDbPath": "D:\\SQLTemp"
},
"resources": [
{
"type": "Microsoft.Network/networkInterfaces",
"apiVersion": "2020-06-01",
"name": "[variables('networkInterfaceName')]",
"location": "[parameters('location')]",
"properties": {
"ipConfigurations": [
{
"name": "ipconfig1",
"properties": {
"subnet": {
"id": "[variables('subnetRef')]"
},
"privateIPAllocationMethod": "Static",
"privateIPAddress": "[parameters('ipAddress')]",
"privateIPAddressVersion": "IPv4"
}
}
],
"enableAcceleratedNetworking": false
}
},
{
"type": "Microsoft.Compute/virtualMachines",
"apiVersion": "2020-06-01",
"name": "[parameters('virtualMachineName')]",
"location": "[parameters('location')]",
"dependsOn": [
"[resourceId('Microsoft.Network/networkInterfaces/', variables('networkInterfaceName'))]"
],
"properties": {
"hardwareProfile": {
"vmSize": "[parameters('virtualMachineSize')]"
},
"storageProfile": {
"osDisk": {
"createOption": "fromImage",
"managedDisk": {
"storageAccountType": "StandardSSD_LRS"
}
},
"imageReference": {
"publisher": "MicrosoftSQLServer",
"offer": "[parameters('imageOffer')]",
"sku": "[parameters('sqlSku')]",
"version": "latest"
},
"copy": [
{
"name": "dataDisks",
"count": "[add(parameters('sqlDataDisksCount'), parameters('sqlLogDisksCount'))]",
"input": {
"lun": "[copyIndex('dataDisks')]",
"createOption": "[variables('dataDisks').createOption]",
"caching": "[if(greaterOrEquals(copyIndex('dataDisks'), parameters('sqlDataDisksCount')) ,'None', variables('dataDisks').caching )]",
"writeAcceleratorEnabled": "[variables('dataDisks').writeAcceleratorEnabled]",
"diskSizeGB": "[variables('dataDisks').diskSizeGB]",
"managedDisk": {
"storageAccountType": "[variables('dataDisks').storageAccountType]"
}
}
}
]
},
"networkProfile": {
"networkInterfaces": [
{
"id": "[resourceId('Microsoft.Network/networkInterfaces', variables('networkInterfaceName'))]"
}
]
},
"osProfile": {
"computerName": "[parameters('virtualMachineName')]",
"adminUsername": "[parameters('adminUsername')]",
"adminPassword": "[parameters('adminPassword')]",
"windowsConfiguration": {
"enableAutomaticUpdates": true,
"provisionVmAgent": true
}
}
}
},
{
"type": "Microsoft.SqlVirtualMachine/SqlVirtualMachines",
"apiVersion": "2017-03-01-preview",
"name": "[last(split(resourceId('Microsoft.Compute/virtualMachines', parameters('virtualMachineName')),'/'))]",
"location": "[parameters('location')]",
"dependsOn": [
"[resourceId('Microsoft.Compute/virtualMachines', parameters('virtualMachineName'))]"
],
"properties": {
"virtualMachineResourceId": "[resourceId('Microsoft.Compute/virtualMachines', parameters('virtualMachineName'))]",
"sqlManagement": "Full",
"SqlServerLicenseType": "PAYG",
"StorageConfigurationSettings": {
"DiskConfigurationType": "[variables('diskConfigurationType')]",
"StorageWorkloadType": "[parameters('storageWorkloadType')]",
"SQLDataSettings": {
"LUNs": "[variables('dataDisksLUNs')]",
"DefaultFilePath": "[parameters('dataPath')]"
},
"SQLLogSettings": {
"Luns": "[variables('logDisksLUNs')]",
"DefaultFilePath": "[parameters('logPath')]"
},
"SQLTempDbSettings": {
"DefaultFilePath": "[variables('tempDbPath')]"
}
}
}
}
],
"outputs": {
"virtualMachine": {
"type": "object",
"value": "[reference(parameters('virtualMachineName'))]"
}
}
}
For your output use:
"outputs": {
"virtualMachine": {
"type": "object",
"value": "[reference(resourceId('Microsoft.Compute/virtualMachines', parameters('virtualMachineName')))]"
},
"sqlVirtualMachine": {
"type": "object",
"value": "[reference(resourceId('Microsoft.SqlVirtualMachine/SqlVirtualMachines', parameters('virtualMachineName')))]"
}
}
Depending on what you're after... You can name them the same, but any reference to them (dependsOn, reference()) needs to be unambiguous.
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 use the Github library "json-schema" to validate JSON against a custom schema. But I am having trouble validating the following JSON against my defined schema.
JSON holding 2 news entries:
[{
"bodytext": "Lorem ipsum",
"datetime": "2018-01-29T13:18:56+0100",
"falMedia": {
"00000000519602e500007f310096b8e2": {
"alternative": null,
"description": "The description",
"link": "",
"pid": 6043,
"processedFile": {
"publicUrl": "image01.png"
},
"title": null,
"uid": 52925
},
"0000000051960a1700007f310096b8e2": {
"alternative": null,
"description": "Another description",
"link": "",
"pid": 6043,
"processedFile": {
"publicUrl": "images/picture01.jpg"
},
"title": null,
"uid": 52927
}
},
"falRelatedFiles": [ ],
"istopnews": true,
"pid": 6043,
"teaser": "A short lorem teaser",
"title": "The message title",
"uid": 51911
},
{
"bodytext": "Hello World",
"datetime": "2018-01-29T13:24:33+0100",
"falMedia": [ ],
"falRelatedFiles": [ ],
"istopnews": false,
"pid": 339,
"teaser": null,
"title": "Just a short message",
"uid": 51915
}]
This is my schema against which I try to validate:
{
"$schema": "http://json-schema.org/draft-04/schema",
"title": "FPÖ News",
"description": "Schema for FPÖ News articles accesed by the mobile apps",
"type": "array",
"items": {
"additionalProperties": false,
"properties": {
"bodytext": {
"type": "string"
},
"datetime": {
"type": "string"
},
"falMedia": {
"anyOf": [
{
"type": "object",
"patternProperties": {
"^[0-9abcde]*$": {
"type": "object",
"properties": {
"alternative": {
"type": ["null", "string"]
},
"description": {
"type": "string"
},
"link": {
"type": "string"
},
"pid": {
"type": "integer"
},
"processedFile": {
"type": "object",
"properties": {
"additionalProperties": false,
"publicUrl": {
"type": "string"
}
}
},
"title": {
"type": "string"
},
"uid": {
"type": "integer"
}
},
"additionalProperties": false
}
}
},
{
"type": "array"
}
]
},
"falRelatedFiles": {
"type": "array"
},
"istopnews": {
"type": "boolean"
},
"pid": {
"type": "integer"
},
"teaser": {
"type": ["string", "null"]
},
"title": {
"type": "string"
},
"uid": {
"type": "integer"
}
},
"required": [
"bodytext",
"datetime",
"istopnews",
"pid",
"teaser",
"title",
"uid"
]
}
}
It seems to me that everything underneath the part "patternProperties" is not concidered when validating.
My issue is, that the keys for the objects underneath "falMedia" are generated dynamically. Therefore I do not know these values. I thought about using the "patternProperties". But when I change the values of the "falMedia" entries in the "news" to something which (according to the supplied regex under patternProperties) is not valid, the library still says that everything is fine.
Am I missing out on something here?
Is my schema false?
I would greatly appriciate any help.
Thanks
Klaus
Your problem seems to be that your regex should be "^[0-9abcdef]*$" instead of "^[0-9abcde]*$". Because you're missing the "f", patternProperties doesn't match any of the values and therefore doesn't constraint the properties in "falMedia".
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.
I've been trying to create a JSON Schema and have been using an online validation tool http://jsonschemalint.com/. I made a change to my JSON object that I expected to fail against my schema but it didn't - so I think I must have made a mistake somewhere. Can anyone explain to my why the following change doesn't cause a validation error?
Schema
{
"title": "Control Configuration Array",
"description": "An array of the configurations",
"type": "array",
"minItems": 1,
"items": {
"group": {
"title": "Control Grouping",
"description": "Represents a logical grouping of controls",
"type": "object",
"properties": {
"value": {
"title": "Group Label",
"description": "The label to use for the group",
"type": "string"
},
"sortIndex": {
"title": "Sort Index",
"description": "The order in which the groups appear",
"type": "number",
"minimum": 0
},
"cssClass": {
"title": "Group CSS",
"description": "The CSS class to apply to the group label",
"type": "string"
},
"controls": {
"title": "Controls",
"description": "The set of controls within this group",
"type": "array",
"minItems": 1,
"required": true,
"items": {
"config": {
"title": "Control Configuration",
"description": "The main configuration object for a control and its associated dependencies",
"type": "object",
"properties": {
"id": {
"title": "Control ID",
"description": "The identifier for the control set which will be used in dependencies",
"type": "string",
"required": true
},
"sortIndex": {
"title": "Sort Index",
"description": "The order in which the controls appear",
"type": "number",
"minimum": 0
},
"label": {
"title": "Label",
"description": "Describes the label for the control group",
"type": "object",
"properties": {
"value": {
"title": "Caption",
"description": "The caption to place in the label",
"type": "string"
},
"cssClass": {
"title": "Label CSS Classes",
"description": "The CSS classes to apply to the label, separated with spaces",
"type": "string"
},
"tooltipText": {
"title": "Tooltip",
"description": "The tooltip to apply to the label and control",
"type": "string"
}
}
},
"control": {
"title": "Control",
"description": "Describes the control for the control group",
"type": "object",
"required": true,
"properties": {
"type": {
"title": "Control Type",
"description": "The type of control that should be displayed",
"type": "string",
"enum": [
"text",
"radio",
"dropdown",
"checkbox",
"color",
"date",
"datetime",
"search",
"email",
"url",
"tel",
"number",
"range",
"month",
"week",
"time",
"datetime-local"
]
},
"options": {
"title": "Avaliable Options",
"description": "The set of avaliable options for all selection controls (e.g. radio, dropdown)",
"type": "array"
},
"value": {
"title": "The current value of the control",
"description": "This is the inital value or selected value of the control",
"type": "object",
"required": true
},
"cssClass": {
"title": "Control CSS Classes",
"description": "The CSS classes to apply to the control, separated with spaces",
"type": "string"
}
}
},
"dependencies": {
"title": "Dependencies",
"description": "Describes the dependencies between this and other controls",
"type": "object",
"properties": {
"enabled": {
"title": "Enabled",
"description": "The properties to determine if the control should be enabled or not",
"type": "object",
"properties": {
"targetID": {
"title": "Enabled Target ID",
"description": "The ID of the target control, whose value must match one of the target values for this control to be enabled",
"type": "string",
"required": true
},
"targetValues": {
"title": "Enabled target values",
"description": "The set of values which if selected in the target control will cause this control to be enabled",
"type": "array",
"required": true
}
}
},
"display": {
"title": "Display",
"description": "The properties to determine if the control should be displayed or not",
"type": "object",
"properties": {
"targetID": {
"title": "Display Target ID",
"description": "The ID of the target control, whose value must match one of the target values for this control to be displayed",
"type": "string",
"required": true
},
"targetValues": {
"title": "Display target values",
"description": "The set of values which if selected in the target control will cause this control to be displayed",
"type": "array",
"required": true
}
}
}
}
},
"validation": {
"title": "Validation",
"description": "Describes the validation of the control value",
"type": "object",
"properties": {
"required": {
"title": "Required",
"description": "Whether the field is required",
"type": "boolean"
},
"min": {
"title": "Minimum",
"description": "The minimum value that the control is allowed",
"type": "number"
},
"max": {
"title": "Maximum",
"description": "The maximum value that the control is allowed",
"type": "number"
},
"minLength": {
"title": "Minimum Length",
"description": "The minimum length that the control is allowed",
"type": "integer"
},
"maxLength": {
"title": "Maximum Length",
"description": "The maximum length that the control is allowed",
"type": "integer"
},
"pattern": {
"title": "Regex Pattern",
"description": "A regex pattern to use for validation",
"type": "string"
},
"step": {
"title": "Increment Step",
"description": "An increment check that must be met - generally combine with min/max",
"type": "number"
},
"email": {
"title": "Email",
"description": "Whether the field must be an email address",
"type": "boolean"
},
"equal": {
"title": "Equals",
"description": "Ensure the field equals the other object",
"type": "object"
},
"notEqual": {
"title": "Not Equals",
"description": "Ensure the field does not equal the other object",
"type": "object"
},
"date": {
"title": "Date",
"description": "Whether the field must be a date",
"type": "boolean"
},
"dateISO": {
"title": "Date ISO",
"description": "Whether the field must be an ISO date",
"type": "boolean"
},
"number": {
"title": "Number",
"description": "Whether the field must be a number",
"type": "boolean"
},
"digit": {
"title": "Digit",
"description": "Whether the field must be a digit",
"type": "boolean"
}
}
}
}
}
}
}
}
}
}
}
JSON
[
{
"value": "Group1",
"cssClass": "red",
"sortIndex": 1,
"controls": [
{
"id": "ConfigType",
"sortIndex": 1,
"label": {
"value": "Configuration Type",
"cssClass": "label",
"tooltipText": "Configuration Type Tooltip"
},
"control": {
"type": "radio",
"options": [
"Single Deck",
"Level"
],
"value": "Single Deck",
"cssClass": "control"
}
},
{
"id": "AppType",
"sortIndex": 2,
"label": {
"value": "Application Type",
"cssClass": "label",
"tooltipText": "Application Type Tooltip"
},
"control": {
"type": "dropdown",
"options": [
"Other",
"Other2"
],
"value": "Other",
"cssClass": "red"
},
"dependencies": {
"enabled": {
"targetID": "ConfigType",
"targetValues": [
"Level"
]
},
"display": {
"targetID": "ConfigType",
"targetValues": [
"Level"
]
}
}
},
{
"id": "textType",
"label": {
"value": "Text Type",
"cssClass": "label",
"tooltipText": "text Type Tooltip"
}
}
]
}
]
Change
Find "targetID" : "ConfigType" under either the enabled or display dependency. Remove this line. This should then fail as these are both required fields according to the schema. However it doesn't seem to fail...
First I would recommend you move to draft 4 which have some improvements (required is provided in an array).
jsonschemalint is using draft 3. Afaik "items" constraint has not changed. You can provide a boolean value, an object or one array of objects.
In your case, you have provided one object-schema but incorrectly. "group" and "config" labels are not necessary. For instance, given the following json object in draft 3:
[{}]
This schema (similar as yours) validates the data:
{
"type" : "array",
"minItems" : 1,
"items" : {
"unnecesaryLabel" : {
"type" : "object",
"properties" : {
"one" : {
"required" : true
}
}
}
}
}
And this makes the data invalid:
{
"type" : "array",
"minItems" : 1,
"items" : {
"type" : "object",
"properties" : {
"one" : {
"required" : true
}
}
}
}