Related
I developing a method that accepts various messages and returns the some result. The main goal is that message formats can be added without rebuilding the project. Two types of the messages is below:
{
"PushToken": "ksjdfhskfhskdjfhskjdfhk",
"AlertŠµ": "ssffsdfsdfsdfsdfsdfsfs sfsdfsdf sfsdfsdfs",
"Priority": 5,
"IsBackground": false
}
and
{
"DeviceToken": "ksjdfhskfhskdjfhskjdfhkkh7khsdfjk8sdfsdfsddddddddddddddd",
"Message": "ssffsdfsdfsdfsdfsdfsfs sfsdfsdf sfsdfsdfs",
"Title": "asdasdas",
"Condition": "asfdasf"
}
I thinked how to validate messages and decided using json schema's. They are below:
{
"title":"IOS",
"description": "IOS Message",
"type": "object",
"properties": {
"PushToken": { "type": "string", "maxLength": 50 },
"Alert": { "type": "string", "maxLength": 2000 },
"Priority": { "type": "number", "default": 10 },
"IsBackground": { "type": "boolean", "default": true }
},
"required":[
"PushToken",
"Alert"
],
"additionalProperties": false
}
and
{
"title":"Android",
"description": "Android message",
"type": "object",
"properties": {
"DeviceToken": { "type": "string", "maxLength": 50 },
"Message": { "type": "string", "maxLength": 2000 },
"Title": { "type": "string", "maxLength": 255 },
"Condition": { "type": "string", "maxLength": 2000 }
},
"required":[
"DeviceToken",
"Message",
"Title"
],
"additionalProperties": false
}
For validating I using thomething like that:
JSchema schema = JSchema.Parse(iosJsonSchema);
IList<string> errorMessages;
bool valid = iosJsonMessage.IsValid(schema, out errorMessages); //iosJsonMessage - JObject type
In IList<string> messages I receive all errors. In bool valid variable I receive validation result.
Is there a way to check only properties names of the json request? And only those names that are declare in required section of the json schema. I want to do this for understanding the type of the message.
And a more general question. Is this an acceptable solution for task that I described above?
Thanks.
I'm testing NewtonSoft's JsonSchema package and have the following code
string schemaJson = File.ReadAllText("c:\\temp\\schema.txt");
JsonSchema schema = JsonSchema.Parse(schemaJson);
When I test the schema on https://www.jsonschemavalidator.net/ it executes correctly, but when I run the above code locally I get an ArgumentException "Can not convert Array to Boolean".
Here is the schema:
{
"$schema": "http://json-schema.org/draft-07/schema",
"$id": "http://example.com/root.json",
"type": "object",
"title": "The Root Schema",
"description": "The root schema is the schema that comprises the entire JSON document.",
"default": {},
"required": [
"checked",
"dimensions",
"id",
"name",
"price",
"tags"
],
"properties": {
"checked": {
"$id": "#/properties/checked",
"type": "boolean",
"title": "The Checked Schema",
"description": "An explanation about the purpose of this instance.",
"default": false,
"examples": [
false
]
},
"dimensions": {
"$id": "#/properties/dimensions",
"type": "object",
"title": "The Dimensions Schema",
"description": "An explanation about the purpose of this instance.",
"default": {},
"examples": [
{
"height": 10.0,
"width": 5.0
}
],
"required": [
"width",
"height"
],
"properties": {
"width": {
"$id": "#/properties/dimensions/properties/width",
"type": "integer",
"title": "The Width Schema",
"description": "An explanation about the purpose of this instance.",
"default": 0,
"examples": [
5
]
},
"height": {
"$id": "#/properties/dimensions/properties/height",
"type": "integer",
"title": "The Height Schema",
"description": "An explanation about the purpose of this instance.",
"default": 0,
"examples": [
10
]
}
}
},
"id": {
"$id": "#/properties/id",
"type": "integer",
"title": "The Id Schema",
"description": "An explanation about the purpose of this instance.",
"default": 0,
"examples": [
1
]
},
"name": {
"$id": "#/properties/name",
"type": "string",
"title": "The Name Schema",
"description": "An explanation about the purpose of this instance.",
"default": "",
"examples": [
"A green door"
]
},
"price": {
"$id": "#/properties/price",
"type": "number",
"title": "The Price Schema",
"description": "An explanation about the purpose of this instance.",
"default": 0,
"examples": [
12.5
]
},
"tags": {
"$id": "#/properties/tags",
"minItems": 3,
"type": "array",
"title": "The Tags Schema",
"description": "An explanation about the purpose of this instance.",
"default": [],
"examples": [
[
"home",
"green"
]
],
"items": {
"$id": "#/properties/tags/items",
"type": "string",
"title": "The Items Schema",
"description": "An explanation about the purpose of this instance.",
"default": "",
"examples": [
"home",
"green"
]
}
}
}
}
and here is the (invalid) JSON that I use on the website to test the schema validation:
{
"checked": "false",
"dimensions": {
"width": 5,
"height": 10
},
"id": 1,
"name": "A green door",
"price": 12.5,
"tags": [
"home",
"green"
]
}
I was able to reproduce your problem here.
It appears that you are using the JsonSchema component from the Newtonsoft.Json package. As noted in the documentation, this component is obsolete and has been replaced by a newer JSchema component which is in a separate Newtonsoft.Json.Schema package.
If you use the newer component your schema loads as expected.
I am wrting a Function ARM template for CI/CD the function is already hosted on the Azure portal Now I decided to create an ARM function template and am getting the below error. It saying I cannot create a resource which already exists. I know the resource already exists but I want to create a CI/CD pipline based on the template. I have tried the incremental mode but it seems I am missing something. Is there any guidance online? I have taken the Azure Function Template from the AZURE Git.
C:\Program Files\Microsoft SDKs\Azure.NET SDK\v2.9> az group deployment validate --mode Incremental --resource-group cloud-shell-storage-southeastasia --template-file azuredeploy.json
Please provide string value for 'appName' (? for help): SchedulerHttpFunctionSample
azuredeploy.json
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"appName": {
"type": "string",
"metadata": {
"description": "The name of the function app that you wish to create."
}
},
"storageAccountType": {
"type": "string",
"defaultValue": "Standard_LRS",
"allowedValues": [
"Standard_LRS",
"Standard_GRS",
"Standard_RAGRS"
],
"metadata": {
"description": "Storage Account type"
}
},
"location": {
"type": "string",
"defaultValue": "[resourceGroup().location]",
"metadata": {
"description": "Location for all resources."
}
},
"runtime": {
"type": "string",
"defaultValue": "node",
"allowedValues": [
"node",
"dotnet",
"java"
],
"metadata": {
"description": "The language worker runtime to load in the function app."
}
}
},
"variables": {
"functionAppName": "[parameters('appName')]",
"hostingPlanName": "[parameters('appName')]",
"applicationInsightsName": "[parameters('appName')]",
"storageAccountName": "[concat(uniquestring(resourceGroup().id), 'azfunctions')]",
"storageAccountid": "[concat(resourceGroup().id,'/providers/','Microsoft.Storage/storageAccounts/', variables('storageAccountName'))]",
"functionWorkerRuntime": "[parameters('runtime')]"
},
"resources": [
{
"type": "Microsoft.Storage/storageAccounts",
"name": "[variables('storageAccountName')]",
"apiVersion": "2018-12-01",
"location": "[parameters('location')]",
"kind": "Storage",
"sku": {
"name": "[parameters('storageAccountType')]"
},
"properties":{
"mode":"Incremental"
}
},
{
"type": "Microsoft.Web/serverfarms",
"apiVersion": "2018-02-01",
"name": "[variables('hostingPlanName')]",
"location": "[parameters('location')]",
"sku": {
"name": "Y1",
"tier": "Dynamic"
},
"properties": {
"mode":"Incremental",
"name": "[variables('hostingPlanName')]",
"computeMode": "Dynamic"
}
},
{
"apiVersion": "2018-02-01",
"type": "Microsoft.Web/sites",
"name": "[variables('functionAppName')]",
"location": "[parameters('location')]",
"kind": "functionapp",
"dependsOn": [
"[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]",
"[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]"
],
"properties": {
"serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]",
"mode":"Incremental",
"siteConfig": {
"appSettings": [
{
"name": "AzureWebJobsStorage",
"value": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('storageAccountName'), ';AccountKey=', listKeys(variables('storageAccountid'),'2015-05-01-preview').key1)]"
},
{
"name": "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING",
"value": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('storageAccountName'), ';AccountKey=', listKeys(variables('storageAccountid'),'2015-05-01-preview').key1)]"
},
{
"name": "WEBSITE_CONTENTSHARE",
"value": "[toLower(variables('functionAppName'))]"
},
{
"name": "FUNCTIONS_EXTENSION_VERSION",
"value": "~2"
},
{
"name": "WEBSITE_NODE_DEFAULT_VERSION",
"value": "~10"
},
{
"name": "APPINSIGHTS_INSTRUMENTATIONKEY",
"value": "[reference(resourceId('microsoft.insights/components/', variables('applicationInsightsName')), '2015-05-01').InstrumentationKey]"
},
{
"name": "FUNCTIONS_WORKER_RUNTIME",
"value": "[variables('functionWorkerRuntime')]"
}
]
}
}
},
{
"apiVersion": "2018-02-01",
"name": "[variables('applicationInsightsName')]",
"type": "microsoft.insights/components",
"location": "East US",
"tags": {
"[concat('hidden-link:', resourceGroup().id, '/providers/Microsoft.Web/sites/', variables('applicationInsightsName'))]": "Resource"
},
"properties": {
"ApplicationId": "[variables('applicationInsightsName')]",
"Request_Source": "IbizaWebAppExtensionCreate",
"mode":"Incremental"
}
}
]
}
Azure Error: InvalidResourceLocation
Message: The resource 'SchedulerHttpFunctionSample' already exists in location 'southcentralus' in resource group 'cloud-shell-storage-southeastasia'. A resource with the same name cannot be created in location 'southeastasia'. Please select a new resource name.
It's because that name is already taken. Function App name need to be globally unique.
I would suggest using a suffix. In the variables section create some variables:
"variables": {
"suffix": "[uniqueString(resourceGroup().id, resourceGroup().location)]",
"functionAppName": "[concat(parameters('appName'), variables('suffix'))]"
}
The function uniqueString will generate a unique string base on the information received. So if you redeploy in the same resource group and region the suffix will be the same.
Have a look to this post: http://www.frankysnotes.com/2019/05/how-to-make-your-deployment-successful.html or this video https://www.youtube.com/watch?v=dnb-f4C052w
Validate the JSON with JSON Schema return always true.
Newtonsoft is used for validation and tested here with schema and data.
It return always 'No errors found. JSON validates against the schema'.
Please find my JSON Schema.
{
"schema": {
"definitions": {
},
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "http://example.com/root.json",
"type": "object",
"widget": { "formlyConfig": { "type": "accordion" } },
"title": "The Root Schema",
"required": [
"accordion1",
"accordion2",
"accordion3"
],
"properties": {
"accordion1": {
"$id": "#/properties/accordion1",
"type": "object",
"title": "The Accordion1 Schema",
"required": [
"firstname",
"age"
],
"properties": {
"firstname": {
"$id": "#/properties/accordion1/properties/firstname",
"type": "string",
"title": "The Firstname Schema",
"default": "firstname pvr1"
},
"age": {
"$id": "#/properties/accordion1/properties/age",
"type": "integer",
"title": "The Age Schema",
"default": 21
}
}
},
"accordion2": {
"$id": "#/properties/accordion2",
"type": "object",
"title": "The Accordion2 Schema",
"required": [
"firstname",
"age"
],
"properties": {
"firstname": {
"$id": "#/properties/accordion2/properties/firstname",
"type": "string",
"title": "The Firstname Schema",
"default": "firstName2"
},
"age": {
"$id": "#/properties/accordion2/properties/age",
"type": "integer",
"title": "The Age Schema",
"default": 31
}
}
},
"accordion3": {
"$id": "#/properties/accordion3",
"type": "object",
"title": "The Accordion3 Schema",
"required": [
"firstname",
"age"
],
"properties": {
"firstname": {
"$id": "#/properties/accordion3/properties/firstname",
"type": "string",
"title": "The Firstname Schema",
"default": "firstnaem3"
},
"age": {
"$id": "#/properties/accordion3/properties/age",
"type": "integer",
"title": "The Age Schema",
"default": 10
}
}
}
},
'additionalProperties': false
}
}
Please find JSON
{
"accordion1":{
"firstname":"JSON ACCORD PALANIVELRAJAN",
"age":29
},
"accordion2":{
"firstname":"JSON ACCORD LAKSHMANAN",
"age":39
},
"accordion3":{
"firstname":null,
"age":49
}
}
I tried to change the first name to integer and remove the first in accordion1. It return true for all cases.
Please advise.
Please find the code which validate the JSON with JSON Schema.
model is a JObject and it is a valid JSON.
JsonSchema json_schema = JsonSchema.Parse(schema);
IList<string> messages;
bool valid = model.IsValid(json_schema, out messages);
return valid;
JsonSchema is deprecated, and has moved to a separate package: Newtonsoft.Json.Schema. Using this package, I was able to validate your JSON against your schema (I did remove the outer schema element, as it is actually invalid, and causes schema to not validate properly - I think you might've had it in there because the old JsonSchema class could not parse the schema otherwise!), and get error messages if I changed the JSON to an invalid shape, removed required elements, or changed data to invalid types:
string data = File.ReadAllText("data.json");
string schema = File.ReadAllText("data.schema.json");
var model = JObject.Parse(data);
var json_schema = JSchema.Parse(schema);
IList<string> messages;
bool valid = model.IsValid(json_schema, out messages); // properly validates
I am using .NET Core 2.2, Newtonsoft.Json 12.0.2, and Newtonsoft.Json.Schema 3.0.11, just in case it matters. Please note, the Newtonsoft.Json.Schema package has limitations for commercial use - check licensing!
I am working on project where I need to call Web API which on success send json data along with other data. Now i have JSON schema as per their documentation so I want to parse data as per Schema mentioned so that I get everything in c# .
I know I can create a class manually then parse using Newtonsoft etc.. but Is there any way I can create class from JSON schema and parse output based upon that.
I have tried online tool to convert JSON to c# but as my schema contains property of each filed like whither required or datatype etc.. So not getting exact result even after parsring..
Json schema is as below
{
"description": "Rightmove Realtime Datafeed Json Schema for GetBranchPerformance response",
"type": "object",
"properties": {
"request_id": {
"type": "string",
"required": true,
"description": "The unique ID of the request which this response is associated with"
},
"message": {
"type": "string",
"required": true,
"description": "The message content for the response"
},
"success": {
"type": "boolean",
"required": true,
"description": "Indicates whether or not the request was successful"
},
"request_timestamp": {
"type": "string",
"required": true,
"description": "The time at which the request was received in the format: dd-MM-yyyy HH:mm:ss"
},
"response_timestamp": {
"type": "string",
"required": true,
"description": "The time at which the response was sent in the format: dd-MM-yyyy HH:mm:ss"
},
"replication_lag": {
"type": ["integer", "null"],
"required": false,
"description": "The current lag time for replicating between the three Rightmove data centres in minutes"
},
"export_date": {
"type": ["string", "null"],
"required": false,
"description": "The date for the export period in the format: dd-MM-yyyy"
},
"branch": {
"type": ["object","null"],
"required": false,
"description": "Information about the branch for which the metrics are being generated",
"properties": {
"branch_id": {
"type": "integer",
"id": "branch_id",
"required": true,
"description": "Unique Rightmove ID for the branch for which the performance metrics are being generated"
}
},
"additionalProperties": false
},
"performance_data": {
"type": ["object","null"],
"required": false,
"description": "Branch performance data, for the selected export date",
"properties": {
"email_leads": {
"type": "integer",
"required": true,
"description": "The total number of email leads received for a given branch, on the specified day"
},
"phone_leads": {
"type": "integer",
"required": true,
"description": "The total number of phone leads received for a given branch, on the specified day"
},
"property_data": {
"type": [
"array",
"null"
],
"id":"property_data",
"required": false,
"description": "Details about performance by property on Rightmove",
"items": {
"type": "object",
"id": "each_property_data",
"required": true,
"properties": {
"agent_ref":{
"type":"string",
"required":true,
"description":"The agent's unique reference for the property"
},
"display_address": {
"type": "string",
"required": true,
"description": "The display address of the property on Rightmove"
},
"price": {
"type": "integer",
"required": true,
"description": "The current listed price for the property on Rightmove"
},
"channel":{
"type":["integer","null"],
"id":"channel",
"required":false,
"enum":[1, 2, null],
"description":"For dual branches it specifies the channel of the property: 1 Sales 2 Lettings"
},
"rightmove_id":{
"type":"integer",
"required":true,
"description":"Rightmove's unique reference for the property"
},
"rightmove_url":{
"type":"string",
"required":true,
"description":"The Rightmove URL for the property"
},
"featured_property":{
"type":"boolean",
"required":true,
"description":"Y/N - was the property a featured property on this date?"
},
"premium_listing":{
"type":"boolean",
"required":true,
"description":"Y/N - was the property a premium listing on this date?"
},
"summary_views": {
"type": ["object","null"],
"id": "summary_views",
"required": false,
"description": "Information on a property's summary views on Rightmove on the date specified",
"properties": {
"total_summary_views": {
"type":"integer",
"required":true,
"description":"The total number of times the property has appeared in a summary view on the requested date"
},
"desktop_summary_views": {
"type":"integer",
"required":true,
"description":"The total number of times the property has appeared in a summary view on the requested date, when viewed from a desktop PC"
},
"mobile_summary_views": {
"type":"integer",
"required":true,
"description":"The total number of times the property has appeared in a summary view on the requested date, when viewed from a mobile device"
}
}
},
"detail_views": {
"type": ["object","null"],
"id": "detail_views",
"required": false,
"description": "Information on a property's detail views on Rightmove on the date specified",
"properties": {
"total_detail_views": {
"type":"integer",
"required":true,
"description":"The total number of detail views of the property on the requested date"
},
"desktop_detail_views": {
"type":"integer",
"required":true,
"description":"The total number of detail views of the property on the requested date, when viewed from a desktop PC"
},
"mobile_detail_views": {
"type":"integer",
"required":true,
"description":"The total number of detail views of the property on the requested date, when viewed from a mobile device"
}
}
}
},
"additionalProperties": false
}
}
},
"additionalProperties": false
},
"errors": {
"type": [
"array",
"null"
],
"required": false,
"description": "The errors causing the request to fail",
"minItems": 0,
"items": {
"type": [
"object",
"null"
],
"required": false,
"properties": {
"error_code": {
"type": "string",
"id": "error_code",
"required": true,
"description": "The unique Rightmove code for the error causing the request to fail"
},
"error_description":{
"type":"string",
"id":"error_description",
"required":true,
"description": "The full description of the error associated with the error code which has been generated"
},
"error_value":{
"type":["string", "null"],
"id":"error_value",
"required":false,
"description": "The value that caused this error"
}
},
"additionalProperties": false
},
"additionalProperties": false
},
"warnings": {
"type": [
"array",
"null"
],
"required": false,
"description": "The warning generated by the request",
"minItems": 0,
"items": {
"type": [
"object",
"null"
],
"required": false,
"properties": {
"warning_code": {
"type": "string",
"id": "warning_code",
"required": true,
"description": "The unique Rightmove warning code generated due to failure to pass all of the business rules"
},
"warning_description":{
"type":"string",
"id":"warning_description",
"required":true,
"description": "The full description of the warning associated with the warning code which has been generated"
},
"warning_value":{
"type":["string", "null"],
"id":"warning_value",
"required":false,
"description": "The value that caused this warning"
}
},
"additionalProperties": false
},
"additionalProperties": false
}
},
"additionalProperties": false
}