Converting the XML to JSON by handling namespace and array - c#

I want to convert a XML to JSON. But due to the namespace,prefix and json array issues I am facing few issues.
Input XML
<notifications xmlns="http://soap.sforce.com/2005/09/outbound">
<OrganizationId>123</OrganizationId>
<ActionId>123</ActionId>
<SessionId xsi:nil="true" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
<EnterpriseUrl>qwe</EnterpriseUrl>
<PartnerUrl>qwe</PartnerUrl>
<Notification>
<Id>123</Id>
<sObject xsi:type="sf:Opportunity" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:sf="urn:sobject.enterprise.soap.sforce.com">
<sf:Id>ao123</sf:Id>
<sf:Amount>60000.0</sf:Amount>
<sf:CreatedDate>2014-11-26T14:45:52.000Z</sf:CreatedDate>
<sf:IsClosed>false</sf:IsClosed>
</sObject>
</Notification>
</notifications>
Output JSON
{
"notifications": {
"OrganizationId": "123",
"ActionId": "123",
"SessionId": {
"#nil": "true"
},
"EnterpriseUrl": "qwe",
"PartnerUrl": "qwe",
"Notification": [
{
"Id": "ao123",
"sObject": {
"#type": "sf:Opportunity",
"Id": "ao123",
"Amount": "60000.0",
"CreatedDate": "2014-11-26T14:45:52.000Z",
"IsClosed": "false"
}
}
]
}
}
So below are few issues which I am facing
Namespace and prefix of XML should not appear in json.
Notification should be a json array even if I receive one
item
So what I have tried so far is removing namespace and prefix using this method and then converting it to JSON using JsonConvert.SerializeXNode. Also to handle the array I can add json:Array="true" as mentioned here
I feel these steps are more of data manipulation and I am looking for some good approaches to achieve same. So I have tried using XSLT and I am able to remove the namespace prefix. fiddle link for XSLT. But I am not sure how to use XSLT to remove prefix and then convert my XML to my expected JSON format(may be using the XSLT xml-to-json options). Looking for a solution for this using XSLT

you can try try this code
var xDoc = XDocument.Parse(xmlString);
xDoc.Root.DescendantNodesAndSelf().OfType<XElement>().Attributes().Where(att => att.IsNamespaceDeclaration).Remove();
xDoc.Root.DescendantNodesAndSelf().OfType<XElement>().ToList().ForEach(node => node.Name = node.Name.LocalName);
var json = JsonConvert.SerializeXNode(xDoc, Newtonsoft.Json.Formatting.Indented, false);
or assuming https://xsltfiddle.liberty-development.net/aUPRNo/1 that after XSLT your xml is
<?xml version="1.0" encoding="UTF-8"?>
<notifications>
<OrganizationId>123</OrganizationId>
<ActionId>123</ActionId>
<SessionId nil="true" />
<EnterpriseUrl>qwe</EnterpriseUrl>
<PartnerUrl>qwe</PartnerUrl>
<Notification>
<Id>123</Id>
<sObject type="sf:Opportunity">
<Id>ao123</Id>
<Amount>60000.0</Amount>
<CreatedDate>2014-11-26T14:45:52.000Z</CreatedDate>
<IsClosed>false</IsClosed>
</sObject>
</Notification>
</notifications>
<notifications>
<OrganizationId>123</OrganizationId>
<ActionId>123</ActionId>
<SessionId nil="true" />
<EnterpriseUrl>qwe</EnterpriseUrl>
<PartnerUrl>qwe</PartnerUrl>
<Notification>
<Id>123</Id>
<sObject type="sf:Opportunity">
<Id>ao123</Id>
<Amount>60000.0</Amount>
<CreatedDate>2014-11-26T14:45:52.000Z</CreatedDate>
<IsClosed>false</IsClosed>
</sObject>
</Notification>
</notifications>
you can use this code to convert it to json
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(xml);
XmlNode node = xmlDoc.SelectSingleNode("notifications");
var json = JsonConvert.SerializeXmlNode(node, Newtonsoft.Json.Formatting.Indented, false);
in both cases the output is the same
{
"notifications": {
"OrganizationId": "123",
"ActionId": "123",
"SessionId": {
"#nil": "true"
},
"EnterpriseUrl": "qwe",
"PartnerUrl": "qwe",
"Notification": {
"Id": "123",
"sObject": {
"#type": "sf:Opportunity",
"Id": "ao123",
"Amount": "60000.0",
"CreatedDate": "2014-11-26T14:45:52.000Z",
"IsClosed": "false"
}
}
}
}

Related

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.

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();
}
}
}

Generating JSON schema from C# class

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)

Convert JSON to XML and save XML

I am trying to convert some JSON to XML and then save it using JSON.NET in C# but i can't seem to get it.
Here is what i have:
using System.XML;
using Newtonsoft;
XmlDocument doc = (XmlDocument)Newtonsoft.Json.JsonConvert.DeserializeXmlNode(json);
XmlTextWriter writer = new XmlTextWriter("json.xml", null);
writer.Formatting = Formatting.Indented;
doc.Save(writer);
I tested your code and it works totally fine for me. According to the documentation for DeserializeXmlNode this should definitely work:
// { "?xml": { "#version": "1.0", "#standalone": "no" }, "root": { "person": [ { "#id": "1", "name": "Alan", "url": "http://www.google.com" }, { "#id": "2", "name": "Louis", "url": "http://www.yahoo.com" } ] } }
string json = "{ \"?xml\": { \"#version\": \"1.0\", \"#standalone\": \"no\" }, \"root\": { \"person\": [ { \"#id\": \"1\", \"name\": \"Alan\", \"url\": \"http://www.google.com\" }, { \"#id\": \"2\", \"name\": \"Louis\", \"url\": \"http://www.yahoo.com\" } ] } }";
System.Xml.XmlDocument xmlDocument = Newtonsoft.Json.JsonConvert.DeserializeXmlNode(json);
System.Xml.XmlTextWriter xmlTextWriter = new System.Xml.XmlTextWriter("json.xml", null);
xmlTextWriter.Formatting = System.Xml.Formatting.Indented;
xmlDocument.Save(xmlTextWriter);
//<?xml version="1.0" standalone="no"?>
//<root>
// <person id="1">
// <name>Alan</name>
// <url>http://www.google.com</url>
// </person>
// <person id="2">
// <name>Louis</name>
// <url>http://www.yahoo.com</url>
// </person>
//</root>
Test your method with the JSON string above, to verify if it works. I would say you are having a problem with your JSON not being valid.
You can validate your JSON for example here:
The JSON Validator

Categories

Resources