how can i get nested data from a JsonConvert.DeserializeObject<dynamic>(example) - c#

Using the example code works correctly to get the non-nested data from "issues", how can I get the nested data from "issues"? In the picture you can see which data we are talking about.
Code:
try
{
var dynObj = JsonConvert.DeserializeObject<dynamic>(strResponseValue);
string records = dynObj["issues"].ToString();
JArray a = JArray.Parse(records);
List<string> colNames = new List<string>() {"expand", "key", "id",
"self" };
string headerRow = "";
foreach (string colName in colNames)
{
headerRow += "\"" + colName + "\";";
}
headerRow = headerRow.TrimEnd(';');
headerRow += "\n";
string dataRows = "";
foreach (var record in a)
{
string thisRecord = "";
foreach (string colName in colNames)
{
thisRecord += "\"" + record[colName] + "\";";
}
thisRecord = thisRecord.TrimEnd(';');
thisRecord += "\n";
dataRows += thisRecord;
}
csvData = headerRow + dataRows;
Console.WriteLine("\ncsvData:");
Console.WriteLine(csvData);
}
catch (Exception ex)
{
Console.WriteLine("Exeption Error" + ex.ToString());
}

If the json is complex, you can let visual studio do the job.
Copy the json content
Use Edit/Paste Special - Paste JSON As Classes
Use the generated Class to deserialize your json content.
For instance deserialize to MyClass (from .Net Fundumentals - JSON Serialize/Deserialize):
MyClass? myclass = JsonSerializer.Deserialize<MyClass>(jsonString);

Related

Epplus how to remove spaces into my excel & resx file

I'm starting to learn c # and Windows form. I create an application that transforms a resx (XML) file into an Excel.
All my code works, my Excel file is created and I can convert it to a resx file.
But, when I open my Excel file, spaces before and after my data has been added like this : Excel cell example. And when I convert it to resx file, it does
Resx file example
Here is my resx => excel code :
//I use a application WindowsForm so any 'LBL' / 'TXT make reference to label or textBox I use them to set file or folder path
private void writeExcel()
{
Dictionary<string, string> dataSave = new Dictionary<string, string>();
var path = LBL_DocumentPath.Text;
XDocument doc = XDocument.Load(path);
IEnumerable<XNode> nodes = doc.Descendants("data");
foreach (XElement node in nodes)
{
string name = node.Attribute("name").Value;
string value = node.Value;
dataSave.Add(name, value);
}
CreateExcel(dataSave);
}
private void CreateExcel(Dictionary<string, string> dico)
{
int i = 1;
FileInfo newFile = new FileInfo(LBL_FolderPath.Text + "/" + TXT_FileName.Text + ".xlsx");
using (ExcelPackage package = new ExcelPackage(newFile))
{
try
{
ExcelWorksheet worksheet = package.Workbook.Worksheets.Add("Inventry");
worksheet.Cells[1, 1].Value = "Name";
worksheet.Cells[1, 2].Value = "value";
worksheet.Cells[1, 3].Value = "translation";
foreach (KeyValuePair<string, string> data in dico)
{
string testMessage = String.Format("{0}", data.Value);
string delSpace = testMessage;
Regex regex = new Regex(#"(\s){2,}");
testMessage = regex.Replace(delSpace, "&");
i++;
worksheet.Cells[i, 1].Value = String.Format("{0}", data.Key);
worksheet.Cells[i, 2].Value = String.Format("{0}", testMessage);
worksheet.Cells.AutoFitColumns();
}
package.Save();
MessageBox.Show("File created ! " + LBL_FolderPath.Text + "\\" + TXT_FileName.Text);
}
catch (Exception)
{
MessageBox.Show("File already exist, checks : " + LBL_DocumentPath.Text + "\\" + TXT_FileName.Text);
}
}
}
If you want all my code, I can give you a dropbox link.
Thanks in advance for any help you can give me.
Math.
Ps: My apologies, my English is not very good. I hope you will understand me correctly
Ok a friend give me solution.
It's my regex which does not work so I replace
string testMessage = String.Format("{0}", data.Value);
string delSpace = testMessage;
Regex regex = new Regex(#"(\s){2,}");
testMessage = regex.Replace(delSpace, "&");
by
string testMessage = String.Format("{0}", data.Value);
testMessage = testMessage.Replace("\n",string.Empty);
testMessage = testMessage.Replace("\r", string.Empty);
testMessage = testMessage.Replace(" ", string.Empty);

Printing Contents of ExpandoObject to an Indented String

I am currently working on a program that takes JSON input and deserializes it using JSON.NET into a dynamic ExpandoObject. Then through a function, I want to dump it out into another textbox to show what it could possibly represent as C# objects. How would I indent my string to show my hierarchical ExpandoObject and take it from a flat list of data to a tree structure of data I can send to a textbox as a string?
Here is some of the code I am using:
if (tbxJSON.Text != "")
{
// Create an ExpandoObjectConverter in order to hold the dynamic parsed JSON.
var converter = new ExpandoObjectConverter();
dynamic convertedJSON = JsonConvert.DeserializeObject<ExpandoObject>(tbxJSON.Text, converter);
tbxCSharp.Text = "";
// Loop through the ExpandoObject and print out all of the values in the dynamic object using a recursive function.
foreach (var property in (IDictionary<string, object>)convertedJSON)
sb.Append(ExpandoToString(property.Value, property.Key));
// Set C# output to contents of StringBuilder.
tbxCSharp.Text = sb.ToString();
}
private string ExpandoToString(object propVal, string propName)
{
string retStr = "";
// If we are dealing with nested JSON
if (propVal.GetType() == typeof(ExpandoObject))
{
// Append this object type.
sb.Append(Indent(indentIdx) + UppercaseFirst(propName) + " " + propName + " consists of..." + Environment.NewLine);
foreach (var prop in (IDictionary<string, object>)propVal)
{
if (prop.Value.GetType() == typeof(ExpandoObject))
sb.Append(ExpandoToString(prop.Value, prop.Key));
else
{
if (prop.Value.GetType() == typeof(List<dynamic>))
{
// TO DO
}
else
sb.Append(ExpandoToString(prop.Value, prop.Key));
}
}
}
else
retStr = propVal.GetType() + " : " + propName + " = " + propVal + Environment.NewLine;
return retStr;
}
Test JSON:
{"airline":"Oceanic","number":815,"departure":{"IATA":"SYD","time":"2004-09-22 14:55","city":"Sydney"},"arrival":{"IATA":"LAX","time":"2004-09-23 10:42","city":"Los Angeles"}}
You should supply your current indent as a parameter to the ExpandoToString() method and increment it any time it calls itself.
private string ExpandoToString(object propVal, string propName, int indent = 0)
{
...
// Append this object type.
sb.Append(Indent(indent) + UppercaseFirst(propName) + " " + propName + " consists of..." + Environment.NewLine);
...
sb.Append(ExpandoToString(propVal, propName, indent + 1) ...);

Best method for comparing XML with string

I am looking for the best way to compare XML data with a string.
the data is stored in a xml called test.xml, and must be compared with the name descendant, if there is a match more info from the xml must be added to a textbox and picture box.
My ( working ) code:
var xmlDocument = XDocument.Load("test.xml"); // XML koppellen
var key1 = xmlDocument.Descendants("NAME"); // XML filepath
var key2 = xmlDocument.Descendants("TITLE"); // XML titel
var key3 = xmlDocument.Descendants("BRAND"); // XML afbeelding
var key4 = xmlDocument.Descendants("TYPE"); // XML merk
var key5 = xmlDocument.Descendants("SOORT"); // XML type
var key6 = xmlDocument.Descendants("NAAM"); // XML naam
List<string> file = new List<string>();
List<string> title = new List<string>();
List<string> brand = new List<string>();
List<string> type = new List<string>();
List<string> soort = new List<string>();
List<string> naam = new List<string>();
int i = 0;
foreach (var key in key1)
{
file.Add(key.Value.Trim());
}
foreach (var key in key2)
{
title.Add(key.Value.Trim());
}
foreach (var key in key3)
{
brand.Add(key.Value.Trim());
}
foreach (var key in key4)
{
type.Add(key.Value.Trim());
}
foreach (var key in key5)
{
soort.Add(key.Value.Trim());
}
foreach (var key in key6)
{
naam.Add(key.Value.Trim());
}
foreach (var Name in naam)
{
if (textBox3.Text.ToString() == Name.ToString())
{
PDFLocation = file[i].ToString();
pictureBox1.Image = pdfhandler.GetPDFthumbNail(PDFLocation);
textBox4.Text =
title[i].ToString() + "\r\n" +
brand[i].ToString() + "\r\n" +
type[i].ToString() + "\r\n" +
soort[i].ToString() + "\r\n" +
textBox3.Text + "\r\n";
}
i++;
}
]
I think this is not the best way to do it, but cant see a better way....
Update: solution:
foreach (XElement element in xmlDocument.Descendants("PDFDATA"))
{
if (textBox3.Text.ToString() == element.Element("NAAM").Value.Trim())
{
PDFLocation = element.Element("NAME").Value.ToString();
pictureBox1.Image = pdfhandler.GetPDFthumbNail(PDFLocation);
textBox4.Text =
element.Element("TITLE").Value + "\r\n" +
element.Element("BRAND").Value + "\r\n";
break;
}
}
Instead of thinking of the xml and a bunch of individual lists of data, it helps to think of it more as objects. Then you can loop through each element one at a time and don't need to split it up into individual lists. This not only removes duplicate code but more importantly creates a better abstraction of the data you are working with. This makes it easier to read and understand what the code is doing.
foreach (XElement element in xmlDocument.Elements())
{
if (textBox3.Text.ToString() == element.Element("NAAM").Value)
{
PDFLocation = element.Element("NAAM").Value;
pictureBox1.Image = pdfhandler.GetPDFthumbNail(PDFLocation);
textBox4.Text =
element.Element("Title").Value + "\r\n" +
element.Element("Brand").Value + "\r\n" +
element.Element("Type").Value + "\r\n"
// access rest of properties...
}
}

put data from simpleDB into data gridview

I was trying to retrieve data from Amazon SimpleDB and currently it only displays data in text like domainName: {attribute1, value2} {attribute1, value2}.
How can I show the data in data grid view? My code is as follows:
public static List<String> GetItemByQuery(IAmazonSimpleDB simpleDBClient, string domainName)
{
List<String> Results = new List<String>(); ;
SelectResponse response = simpleDBClient.Select(new SelectRequest()
{
SelectExpression = "Select * from " + domainName
});
String res = domainName + " has: ";
foreach (Item item in response.Items)
{
res = item.Name + ": ";
foreach (Amazon.SimpleDB.Model.Attribute attribute in item.Attributes)
{
res += "{" + attribute.Name + ", " + attribute.Value + "}, ";
}
res = res.Remove(res.Length - 2);
Results.Add(res);
}
return Results;
}
How you an read here:
http://docs.aws.amazon.com/sdkfornet1/latest/apidocs/html/P_Amazon_SimpleDB_Model_SelectResult_Item.htm
your response.Items is
public List<Item> Item { get; set; }
so you should directly use to DataSource of your Grid, set autogenerate column to your grid to start to view the result

File contents filtering

I'm trying to develop an application which will take the data from a datagrid and based on a drop down menu choice return a csv file with only the selected client . My code is shown below , This links to a previous question I posted howeever I am still getting no values back and I really need to sort this out so I'm wondering if anyone can either see were i'm going wrong or else provide alternatives
//Master inventory export
private void ExportClass_Click(object sender, EventArgs e)
{
StringBuilder str = new StringBuilder();
objSqlCommands2 = new SqlCommands("MasterInventory", "ClientName");
string strString = str.ToString();
string Filepath = txtSaveShareClass.Text.ToString();
str.Append("ISIN ,FundName,Status,Share CCY,Benchmark,NAV Freq,CLASSCODE,SIMULATION,HEDGED,FUNDCCY");
StringManipulation sm = new StringManipulation();
foreach (DataRow dr in this.CalcDataSet.MasterInventory)
{
foreach (object field in dr.ItemArray)
{
str.Append(field.ToString() + ",");
}
str.Replace(",", "\n", str.Length - 1, 1);
}
try
{
System.IO.File.WriteAllText(Filepath, str.ToString());
}
catch (Exception ex)
{
MessageBox.Show("Write Error :" + ex.Message);
}
List<string[]> lsClientList = objStringManipulation.parseCSV(Filepath,cmbClientList .Text.ToCharArray());
foreach (string[] laClient in lsClientList)
{
sm.parseCSV2(Filepath, cmbClientList.Text.ToCharArray());
List<string[]> newFoo = lsClientList.Where(x => x.Contains(cmbClientList.Text)).ToList();
List<string[]> Results = sm.parseCSV2(Filepath, cmbClientList.Text.ToCharArray()).Where(x => x.Contains(cmbClientList.Text)).ToList();
//Refreshs the Client table on display from the
System.IO.File.WriteAllText(Filepath, Results.ToString());
}
this.TableAdapter.Fill(this.CalcDataSet.MasterInventory);
dataGridView2.Update();
}
If all of your variables are filling properly and your Results list contains the data that you expect, then the problem is with your WriteAllText call. You have:
System.IO.File.WriteAllText(Filepath, Results.ToString());
That is not going to produce the output that you seem to expect. It will likely just give you the class name.
Results is a List<string[]>. If you want to output that as a CSV, then you have to enumerate it:
using (var outfile = new StreamWriter(Filepath))
{
foreach (var line in Results)
{
StringBuilder sb = new StringBuilder();
foreach (var field in line)
{
sb.Append(field + ",");
}
sb.Length = sb.Length -1;
outfile.WriteLine(sb.ToString());
}
}

Categories