How to validate json with json schema in NJsonSchema c# - c#

As part of contract tests I have to validate json response I got from rest-endpoint against json-schema present in a file. I'm using NJsonSchema and was not able to perform this.
Json-schema in file is as something below
{
'type': 'object',
'properties': {
'remaining': {
'type': 'integer',
'required': true
},
'shuffled': {
'type': 'boolean',
'required': true
}
'success': {
'type': 'boolean',
'required': true
},
'deck_id': {
'type': 'string',
'required': true
}
}
}
Json I have to validate is something like below
{ 'remaining': 52, 'shuffled': true, 'success': true, 'deck_id': 'b5wr0nr5rvk4'}
Can anyone please throw some light (with examples) on how to validate json with jsonschema using NJsonSchema or Manatee.Json.

Disclaimer: I'm the author of Manatee.Json.
That looks like a draft-03 schema (the required keyword was moved out of the property declaration in draft-04). I'm not sure if NJsonSchema supports schemas that old; Manatee.Json doesn't.
JSON Schema is currently at draft-07, and draft-08 is due out soon.
My suggestion is to rewrite the schema as a later draft by moving the required keyword into the root as a sibling of properties. The value of required becomes an array of strings containing the list of properties that are required.
{
"type": "object",
"properties": {
"remaining": { "type": "integer" },
"shuffled": { "type": "boolean" },
"success": { "type": "boolean" },
"deck_id": { "type": "string" }
},
"required": [ "remaining", "shuffled", "success", "deck_id" ]
}
By doing this, it'll definitely work with Manatee.Json, and I expect it'll work with NJsonSchema as well.
If you have specific questions about using Manatee.Json, hit me up on my Slack workspace. There's a link on the GH readme.

Related

Parsing JSON Using Newtonsoft.Json Without Knowing the Structure

I'm working on a project that involves automating API calls using a Swagger Definition. I download the swagger.json file. The structure of the JSON Object I need to parse is not consistent. When parsing paths, there are a list of objects, then within that they have the methods that can be used for that specific path. I can retrieve just the path using various string methods but my question was, is there a good way to parse json if the JSON is structured in such a way that it does not have a firm key? Here is an example of what I mean:
{"/user": {
"post": {
"tags": [
"user"
],
"summary": "Create user",
"description": "This can only be done by the logged in user.",
"operationId": "createUser",
"consumes": [
"application/json"
],
"produces": [
"application/json",
"application/xml"
],
"parameters": [
{
"in": "body",
"name": "body",
"description": "Created user object",
"required": true,
"schema": {
"$ref": "#/definitions/User"
}
}
],
"responses": {
"default": {
"description": "successful operation"
}
}
}
}
If I wanted to just parse that path and retrieve the method object how could I go about that considering sometimes the object will be "post" or sometimes it will be "get", "put", etc depending on what is allowable for the path.
JObject jsonResp = swaggerDownload();
JObject paths = (JObject)jsonResp["paths"];
foreach (var i in paths)
{
string pathToString = i.ToString();
var shaveSomethings = pathToString.Substring(1, something.Length - 2);
var pathAndJson = shaveSomethings.Split(new[] { ',' }, 2);
string correctJsonStructure = "{\"" + pathAndJson[0] + "\":" + pathAndJson[1] + "}";
JObject bd = JObject.Parse(correctJsonStructure);
//dynamic pathsTest = JsonConvert.DeserializeObject<dynamic>(correctJsonStructure);
//JObject result = JsonConvert.DeserializeObject<JObject>(correctJsonStructure);
//Console.WriteLine(bd["/user"]);
}
The swagger.json file should have full definition of each entity that endpoints return. You can follow How to create Rest API client to get a working client.
I've dealt with an API where responses didn't always match the definition. I saved all responses to a store/log first and then would try to de-serialize JSON. In case of an exception I would go back to store/log and see what was different and update my code to accommodate for the change. After few iterations there were no new changes and the ordeal was over.
Hope that helps.

Can't import JSON file when referencing to another file

I'm using NSwag.OpenaPiDocument.FromJsonAsync() to load a JSON file.
The JSON file is seperated in several files. Unfortunately, I'm getting this error:
Could not resolve the JSON path 'parameters.json#/tagsParam' with the full JSON path 'C:\Users\ribuss\Desktop\Swagger\json\petstore-separate\spec\parameters.json#/tagsParam'
I'm trying to import the following files (by calling the method for swagger.json)
In my application I use the following command:
NSwag.OpenApiDocument.FromJsonAsync(content, "C:/Users/ribuss/Desktop/Swagger/json/petstore-separate/spec/swagger.json").Result; // content is the full json text of swagger.json
Edit:
This is the schema which doesn't work:
{
"tagsParam": {
"name": "tags",
"in": "query",
"description": "tags to filter by",
"required": false,
"type": "array",
"collectionFormat": "csv",
"items": {
"type": "string"
}
},
"limitsParam": {
"name": "limit",
"in": "query",
"description": "maximum number of results to return",
"required": false,
"type": "integer",
"format": "int32"
}
}
I've changed the schema by using definitions and it's working now.

Graph: Filter calendar events by schema property

I have this schema extension:
{
"id": "intnovaction_Docu2EventMetadata",
"description": "Eventos de Docu2",
"targetTypes": [
"event"
],
"status": "Available",
"owner": "d1aaf0fa-549f-4692-8929-22eb90b33099",
"properties": [
{
"name": "ActuacionId",
"type": "String"
},
{
"name": "ExpedienteId",
"type": "String"
}
]
}
I am able to extend event properties using this schema. I can set values for 'ActuacionId' and 'ExpedienteId' on an event and I can get these values through this request: https://graph.microsoft.com/v1.0/me/events?$select=id,intnovaction_Docu2EventMetadata
that returns
{
"#odata.context": "https://graph.microsoft.com/v1.0/$metadata#users('6d418063-df8b-4f47-921b-1072baf4a949')/events(id,intnovaction_Docu2EventMetadata)",
"value": [
{
"#odata.etag": "W/\"FwgXoe8hSUuEcCnxk8/heAAALdjYcQ==\"",
"id": "AAMkAGE1MDUwMDZkLWRmZDctNGMxMi1hN2ZiLTUwNTBlYTc1NmRkYwBGAAAAAABIbknKwqd9SI8d_mLMOg2XBwAXCBeh7yFJS4RwKfGTz_F4AAAAAAENAAAXCBeh7yFJS4RwKfGTz_F4AAAtI8LHAAA=",
"intnovaction_Docu2EventMetadata": {
"ActuacionId": "1",
"ExpedienteId": "2"
}
}
}
the problem comes when I try to filter for those properties:
https://graph.microsoft.com/v1.0/me/events?$select=id,intnovaction_Docu2EventMetadata&$filter=intnovaction_Docu2EventMetadata/ActuacionId eq '1'
Then I am receiving this error response
{
"error": {
"code": "RequestBroker-ParseUri",
"message": "Could not find a property named 'e2_3be22c6901b942889d07616b14e79402_intnovaction_Docu2EventMetadata' on type 'Microsoft.OutlookServices.Event'.",
"innerError": {
"request-id": "4137b6f4-1c8d-4c1e-84fd-02e8ccaab860",
"date": "2017-10-02T19:25:28"
}
}
}
Is it not possible to filter events by schema properties?
It looks like we missed something in our documentation. It's not currently possible to filter on schema extensions defined on Outlook based entity types (events, messages and personal contacts). We could also improve our error messages to make this more clear too. I'll file some items for this.
Hope this helps,

Bot framework - Getting the user's answers from a form generated by json schema

I am using the function to BuildJsonForm to define a form using a JSON schema. I generate the JObject with some parameters the bot asks the user during runtime.
An example of the JObject/JSON I send to the function BuildJsonForm is this one:
`
{
"References": [
"Microsoft.Bot.Connector.dll",
"System.dll",
"mscorlib.dll",
"System.Net.Http.dll"
],
"Imports": [
"Microsoft.Bot.Connector.ThumbnailCard",
"Microsoft.Bot.Connector.StateClient",
"System.Net.Mail",
"System",
"System.Text.RegularExpressions",
"System.Net.Http",
"System.Net",
"System.Text"
],
"type": "object",
"required": [
"username",
"password"
],
"Templates": {
"NotUnderstood": {
"Patterns": [
"I do not understand, Please rephrase that"
]
},
"EnumSelectOne": {
"Patterns": [
"Choose one please"
],
"ChoiceStyle": "Auto"
}
},
"properties": {
"username": {
"Prompt": {
"Patterns": [
"Tell me the {&}, please",
"I need you to especify a {&}, please"
]
},
"type": [
"string",
"null"
],
"Templates": {
"NotUnderstood": {
"Patterns": [
"That is not a valid input"
]
}
}
},
"password": {
"Prompt": {
"Patterns": [
"Tell me the {&}, please",
"I need you to especify a {&}, please"
]
},
"type": [
"string",
"null"
],
"Templates": {
"NotUnderstood": {
"Patterns": [
"That is not a valid input"
]
}
}
}
},
"OnCompletion": "await context.PostAsync(\"Thank you!\"); string files = \"\"; context.PrivateConversationData.TryGetValue<string>(\"Files\", out files); [more code...]"
}
`
I need to send to the database the user's answers to the generated JObject/JSON form's questions, but so far, I haven't found a way to do that.
I also tried accessing the BotData with this line context.PrivateConversationData.TryGetValue<string>("Files", out files);, so I could send the user's answers to the database directly from the "OnCompletion" section of the JSON, but still I can't seem to access to the botdata or context on the OnCompletion section.
Is there any other way I can successfully retrieve the user's responses to the JObject/JSON generated form after the user answers the last question in the form?
It seemed that what was causing the trouble in my project were sending this parameters to the function:
GeneratedForm.BuildJsonForm(channel, user, convers);
since I edited the function without those parameters and I stopped getting the exception specified in the question. I will look for the reason these parameters were causing problems but the solution I found in this case was to define the funtction this way:
GeneratedForm.BuildJsonForm();

Deserializing Chrome Bookmark JSON Data in C#

In response to a question I asked a few days ago, I'm attempting to stretch myself a little, and do something that I've not really focussed on much before. I've done some searching (both here, and in general), but can't find the answers (or even reasonable hints) to what I want to achieve (though, a few things come close-ish).
Basically, I'm trying to deserialize the data for the Google Chrome bookmarks file using the Json.NET library (though, if there's a better alternative, I'm all for that - the documentation for this library is a little confusing in places). I'm a little confused as to the next step to take, due primarily to being used to PHP's fantastic handling of JSON data (using json_decode()), allowing for a single function call, and then simple associative-array access.
The library (Json.NET) wants me to specify an Object type that it can deserialize the JSON data into, but I'm not really sure how to go about structuring such an Object, given the format of the Bookmarks file itself. The format is something along the lines of:
{
"roots": {
"bookmark_bar": {
"children": [ {
"children": [ {
"date_added": "12880758517186875",
"name": "Example URL",
"type": "url",
"url": "http://example.com"
}, {
"date_added": "12880290253039500",
"name": "Another URL",
"type": "url",
"url": "http://example.org"
} ],
"date_added": "12880772259603750",
"date_modified": "12880772452901500",
"name": "Sample Folder",
"type": "folder"
}, {
"date_added": "12880823826333250",
"name": "Json.NET",
"type": "url",
"url": "http://james.newtonking.com/pages/json-net.aspx";
} ],
"date_added": "0",
"date_modified": "12880823831234250",
"name": "Bookmarks bar",
"type": "folder"
},
"other": {
"children": [ ],
"date_added": "0",
"date_modified": "0",
"name": "Other bookmarks",
"type": "folder"
}
},
"version": 1
}
Now, in PHP, I'd be far more used to doing something along the lines of the following, to get the data I wanted, and ending up with 'Json.NET':
$data['roots']['bookmark_bar']['children'][0]['name'];
I can work out, simply enough, what objects to create to represent the data (something like a root object, then a bookmark list object, and finally an individual bookmark object) - but I'm really not sure as to how to implement them, and then get the library to deserialize into the relevant objects correctly.
Any advice that can be offered would be greatly appreciated.
It is not necessary to declare a type that reflects the json structure:
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.IO;
using System;
class Program
{
static void Main(string[] args)
{
string json =
#"
{
""roots"": {
""bookmark_bar"": {
""children"": [ {
""children"": [ {
""date_added"": ""12880758517186875"",
""name"": ""Example URL"",
""type"": ""url"",
""url"": ""http://example.com""
}, {
""date_added"": ""12880290253039500"",
""name"": ""Another URL"",
""type"": ""url"",
""url"": ""http://example.org""
} ],
""date_added"": ""12880772259603750"",
""date_modified"": ""12880772452901500"",
""name"": ""Sample Folder"",
""type"": ""folder""
}, {
""date_added"": ""12880823826333250"",
""name"": ""Json.NET"",
""type"": ""url"",
""url"": ""http://james.newtonking.com/pages/json-net.aspx""
} ],
""date_added"": ""0"",
""date_modified"": ""12880823831234250"",
""name"": ""Bookmarks bar"",
""type"": ""folder""
},
""other"": {
""children"": [ ],
""date_added"": ""0"",
""date_modified"": ""0"",
""name"": ""Other bookmarks"",
""type"": ""folder""
}
},
""version"": 1
}
";
using (StringReader reader = new StringReader(json))
using (JsonReader jsonReader = new JsonTextReader(reader))
{
JsonSerializer serializer = new JsonSerializer();
var o = (JToken)serializer.Deserialize(jsonReader);
var date_added = o["roots"]["bookmark_bar"]["children"][0]["date_added"];
Console.WriteLine(date_added);
}
}

Categories

Resources