Generating JSON schema from C# class - c#

Is there any way to programmatically generate a JSON schema from a C# class?
Something which we can do manually using http://www.jsonschema.net/

Another option which supports generating JSON Schema v4 is NJsonSchema:
var schema = JsonSchema.FromType<Person>();
var schemaJson = schema.ToJson();
The library can be installed via NuGet.
Update for NJsonSchema v9.4.3+:
using NJsonSchema;
var schema = await JsonSchema.FromTypeAsync<Person>();
var schemaJson = schema.ToJson();

This is supported in Json.NET via the Newtonsoft.Json.Schema NuGet package. Instructions on how to use it can be found in the official documentation, but I've also included a simple example below.
JSchemaGenerator generator = new JSchemaGenerator();
JSchema schema = generator.Generate(typeof(Person));
Console.WriteLine(schema.ToString());
//{
// "type": "object",
// "properties": {
// "Name": {
// "type": [ "string", "null" ]
// },
// "Age": { "type": "integer" }
// },
// "required": [ "Name", "Age" ]
//}

JsonSchemaGenerator js = new JsonSchemaGenerator();
var schema = js.Generate(typeof(Person));
schema.Title = typeof(Person).Name;
using (StreamWriter fileWriter = File.CreateText(filePath))
{
fileWriter.WriteLine(schema);
}

For those who land here from google searching for the reverse (generate the C# class from JSON) - I use those fine online tools:
JSON:
http://json2csharp.com/
(Source: http://jsonclassgenerator.codeplex.com/)
XML:
http://xmltocsharp.azurewebsites.net/
(Source: https://github.com/msyoung/XmlToCSharp)

Related

Generate JSON from two different JSON objects without coding custom logic

I have a requirement where an event will emit a JSON following a defined schema = JSON-EventA schema. I have a config(config.json) that follows another JSON-EventB schema. Using data from JSON-EventA and Config from config.json, I have to generate a JSON event data which should follow the JSON-EventB schema. Is this possible to write a function GenerateEventData which takes the eventA data and config to generate EventB data ? Without coding the POCO and writing custom logic to convert from one json to another ? I want to be able to update the JSON-EventA schema, config.json without touching the function GenerateEventData, it should be able to generate data in the new JSON-EventB schema as directed by config.json
Illustrating an example that I want -
// I can get an event data and ensure it follows JSON-EventA schema
string eventAData = GetEvent(A);
/*
eventAData = {"Title": "MyTitle", "Address": {"PING": "123"}}
Follows the below schema
EventASchema = {
"type": "object",
"properties": {
"Title": {
"type": "string"
},
"Address": {
"type": "object",
"properties": {
"PIN": {
"type": "string"
}
}
}
};*/
string config = GetConfig();
// config = {"NewTitle": "Generated ${Title}", "PIN": "000${Address.PIN}", "Country": "US"}
//This is what I want to achieve.
string eventB = GenerateEventData(A, config);
/*
eventB = {"NewTitle": "Generated MyTitle", "PIN": "000123", "Country": "US"}
*/

How to access Json (which was a result of HttpMessage) in C#?

I am writing two applications (Web API's) in .NET . From the app A I want to call a method in Controller of app B using Http Request.
Here
using (var askPensionerDetails = new HttpClient())
{
double pensionToDisburse = 0;
askPensionerDetails.BaseAddress = new Uri("http://localhost:55345/api/pensionerdetails/");
var responseTask = askPensionerDetails.GetAsync("getById?pan=" + inputOfPensioner.PAN);
responseTask.Wait();
var result =responseTask.Result ;
if (result.IsSuccessStatusCode)
{
var readTask = result.Content.ReadFromJsonAsync<object>();
readTask.Wait();
return Ok(readTask.Result);
}
}
The output for this in postman is
{
"name": "bunk seenu",
"dateOfBirth": "1990-01-02T00:00:00",
"pan": "ABCD12351E",
"salaryEarned": 45000,
"allowances": 500,
"pensionType": 1,
"bankDetails": {
"bankName": "SBI",
"accountNumber": "SBI00001BS",
"bankType": 0
}
}
That was a desired output. But the problem is how to access the properties like bankdetails,name,pan,salaryEarned.
I have tried using readTask.Result["name"] but it is throwing error.
I have also tried using result.Content.ReadAsStringASync();
But the output in postman is
{
"name": [],
"dateOfBirth": [],
"pan": [],
"salaryEarned": [],
"allowances": [],
"pensionType": [],
"bankDetails": [
[
[]
],
[
[]
],
[
[]
]
]
}
I don't have class associated with the result type of Json for statement readTask = result.Content.ReadFromJsonAsync(); (As per design constraints).
From the docs:
If you have JSON that you want to deserialize, and you don't have the class to deserialize it into, you have options other than manually creating the class that you need:
Deserialize into a JSON DOM (document object model) and extract what you need from the DOM.
The DOM lets you navigate to a subsection of a JSON payload and deserialize a single value, a custom type, or an array. For information about the JsonNode DOM in .NET 6, see Deserialize subsections of a JSON payload. For information about the JsonDocument DOM, see How to search a JsonDocument and JsonElement for sub-elements.
Use the Utf8JsonReader directly.
Use Visual Studio 2019 to automatically generate the class you need:
Copy the JSON that you need to deserialize.
Create a class file and delete the template code.
Choose Edit > Paste Special > Paste JSON as Classes. The result is a class that you can use for your deserialization target.
You can use Newtonsoft.Json
JObject jo = JObject.Parse(readTask.Result);
var name = jo["name"];
if(string.IsNnullOrEmpty(name)){
///some code
}

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.

Encoding/decoding issue with Facebook json messages. C# parsing

I've download json with my conversations archive. I stuck with odd encoding.
Example of json:
{
"sender_name": "Micha\u00c5\u0082",
"timestamp": 1411741499,
"content": "b\u00c4\u0099d\u00c4\u0099",
"type": "Generic"
},
It should be something like this:
{
"sender_name": "Michał",
"timestamp": 1411741499,
"content": "będę",
"type": "Generic"
},
I'm trying to deserialize it like this:
var result = File.ReadAllText(jsonPath, encodingIn);
JavaScriptSerializer serializer = new JavaScriptSerializer();
serializer.MaxJsonLength = Int32.MaxValue;
var conversation = serializer.Deserialize<Conversation>(System.Net.WebUtility.HtmlDecode(result));
Unfortunately the output is like this:
{
"sender_name": "MichaÅ\u0082",
"timestamp": 1411741499,
"content": "bÄ\u0099dÄ\u0099",
"type": "Generic"
},
Anyone know how Facebook encoding the json? I've tried several methods but without results.
Thanks for your help.
Here is the answer:
private string DecodeString(string text)
{
Encoding targetEncoding = Encoding.GetEncoding("ISO-8859-1");
var unescapeText = System.Text.RegularExpressions.Regex.Unescape(text);
return Encoding.UTF8.GetString(targetEncoding.GetBytes(unescapeText));
}
I've collect all answers, mixed them and here we are. Thank you.

Parsing a JSON dictionary that contains the same key with different casing

I have a problem;
I would to know if there is a method to parse json file without having a unique format. So it may have different attributes but all of them contain the attribute Status but it can be in double.
{
"requestid": "1111",
"message": "db",
"status": "OK",
"data": [
{
"Status": "OK", // this one I would to test first to read the other attributes
"fand": "",
"nalDate": "",
"price": 1230000,
"status": 2
}
]
}
With https://www.newtonsoft.com/json
Data data = JsonConvert.DeserializeObject<Data>(json);
And create the class Data with the interesting data inside the json
The defacto standard Json serializer for .NET is Newtonsoft.Json (How to install). You can parse the Json into an object graph and work on that in any order you like:
namespace ConsoleApp3
{
using System;
using Newtonsoft.Json.Linq;
class Program
{
static void Main()
{
var text = #"{
'requestid': '1111',
'message': 'db',
'status': 'OK',
'data': [
{
'Status': 'OK', // this one I would to test first to read the other attributes
'fand': '',
'nalDate': '',
'price': 1230000,
'status': 2
}
]
}";
var json = JObject.Parse(text);
Console.WriteLine(json.SelectToken("data[0].Status").Value<string>());
Console.ReadLine();
}
}
}

Categories

Resources