looping through json array in c# - c#

I have a json string like,
{"objectType" : "Subscriber", "objectList":[{"firstName":"name1","email":"email#example.com","address":"exampleAddress"},{"firstName":"name2","email":"email2#example.com","address":"exampleAddress2"}]}
I need to parse it in my C# code. I have tried,
JavaScriptSerializer json_serializer = new JavaScriptSerializer();
object routes_list = json_serializer.DeserializeObject(myjson here);
But i cant loop through the "objectList" array. How it can be done?

var jsonObj = new JavaScriptSerializer().Deserialize<RootObj>(json);
foreach (var obj in jsonObj.objectList)
{
Console.WriteLine(obj.address);
}
public class ObjectList
{
public string firstName { get; set; }
public string email { get; set; }
public string address { get; set; }
}
public class RootObj
{
public string objectType { get; set; }
public List<ObjectList> objectList { get; set; }
}
Hint: You can use this site to convert your json string to c# classes
EDIT
using Json.Net
dynamic jsonObj = JsonConvert.DeserializeObject(json);
foreach (var obj in jsonObj.objectList)
{
Console.WriteLine(obj.address);
}

var routes_list = (Dictionary<string, object>)json_serializer.DeserializeObject(myjson);
foreach (var record in routes_list)
{
Console.WriteLine(record);
}

This worked for me, converts to JSON to YAML essentially
string JSONDeserialized {get; set;}
public int indentLevel;
private bool JSONDictionarytoYAML(Dictionary<string, object> dict)
{
bool bSuccess = false;
indentLevel++;
foreach (string strKey in dict.Keys)
{
string strOutput = "".PadLeft(indentLevel * 3) + strKey + ":";
JSONDeserialized+="\r\n" + strOutput;
object o = dict[strKey];
if (o is Dictionary<string, object>)
{
JSONDictionarytoYAML((Dictionary<string, object>)o);
}
else if (o is ArrayList)
{
foreach (object oChild in ((ArrayList)o))
{
if (oChild is string)
{
strOutput = ((string)oChild);
JSONDeserialized += strOutput + ",";
}
else if (oChild is Dictionary<string, object>)
{
JSONDictionarytoYAML((Dictionary<string, object>)oChild);
JSONDeserialized += "\r\n";
}
}
}
else
{
strOutput = o.ToString();
JSONDeserialized += strOutput;
}
}
indentLevel--;
return bSuccess;
}
usage
Dictionary<string, object> JSONDic = new Dictionary<string, object>();
JavaScriptSerializer js = new JavaScriptSerializer();
try {
JSONDic = js.Deserialize<Dictionary<string, object>>(inString);
JSONDeserialized = "";
indentLevel = 0;
DisplayDictionary(JSONDic);
return JSONDeserialized;
}
catch (Exception)
{
return "Could not parse input JSON string";
}

Related

Convert JSON String from Camel case to Pascal case using C#

I'm having a JSON string, it has Key in the form of Camel-case but I need to convert the Key to Pascal-case.
Actual JSON String
string jsonString = "{\"personName\":{\"firstName\":\"Emma\",\"lastName\":\"Watson\"}}";
Expected JSON String : Needs to convert from the above JSON string.
string jsonString = "{\"PersonName\":{\"FirstName\":\"Emma\",\"LastName\":\"Watson\"}}";
Kindly assist me how to convert this using C#.
Because I can't sleep.
If you define the following static class of extension methods...
public static class JsonExtensions
{
public static void Capitalize(this JArray jArr)
{
foreach(var x in jArr.Cast<JToken>().ToList())
{
var childObj = x as JObject;
if(childObj != null)
{
childObj.Capitalize();
continue;
}
var childArr = x as JArray;
if(childArr != null)
{
childArr.Capitalize();
continue;
}
}
}
public static void Capitalize(this JObject jObj)
{
foreach(var kvp in jObj.Cast<KeyValuePair<string,JToken>>().ToList())
{
jObj.Remove(kvp.Key);
var newKey = kvp.Key.Capitalize();
var childObj = kvp.Value as JObject;
if(childObj != null)
{
childObj.Capitalize();
jObj.Add(newKey, childObj);
return;
}
var childArr = kvp.Value as JArray;
if(childArr != null)
{
childArr.Capitalize();
jObj.Add(newKey, childArr);
return;
}
jObj.Add(newKey, kvp.Value);
}
}
public static string Capitalize(this string str)
{
if (string.IsNullOrEmpty(str))
{
throw new ArgumentException("empty string");
}
char[] arr = str.ToCharArray();
arr[0] = char.ToUpper(arr[0]);
return new string(arr);
}
}
You can:
void Main()
{
string jsonString =
"{\"personName\":{\"firstName\":\"Emma\",\"lastName\":\"Watson\"}}";
var jObj = JObject.Parse(jsonString);
jObj.Capitalize();
Console.WriteLine(jObj.ToString()); //yay!
}

Insufficient Memory error being thrown

namespace Calendar
{
public partial class MainCalendar : Form
{
private JArray items;
private List<String> AMList = new List<String>();
private List<String> PMList = new List<String>();
private List<String> accessToCalendarFilepath = new List<String>();
private List<CalendarModel> people;
private List<List<CalendarModel>> managers = new List<List<CalendarModel>>();
private List<String> userSelection = new List<String>();
private bool authorizedAccess = false;
private String javaScriptFileContainingJSONObject = "";
public MainCalendar()
{
InitializeComponent();
var locationInformation = System.Environment.CurrentDirectory + Path.DirectorySeparatorChar + "location.json";
using (StreamReader file = File.OpenText(locationInformation))
using (JsonTextReader reader = new JsonTextReader(file))
{
JArray o = (JArray)JToken.ReadFrom(reader);
items = o;
}
foreach (var item in items.Children())
{
var itemProperties = item.Children<JProperty>();
// you could do a foreach or a linq here depending on what you need to do exactly with the value
var myElement = itemProperties.FirstOrDefault(x => x.Name == "name");
var myElementValue = myElement.Value; ////This is a JValue type
if(myElementValue.ToString().Contains("AM"))
{
AMList.Add(myElementValue.ToString());
}
if (myElementValue.ToString().Contains("PM"))
{
PMList.Add(myElementValue.ToString());
}
}
mondayAM.DataSource = AMList.ToArray();
tuesdayAM.DataSource = AMList.ToArray();
wednesdayAM.DataSource = AMList.ToArray();
thursdayAM.DataSource = AMList.ToArray();
fridayAM.DataSource = AMList.ToArray();
mondayPM.DataSource = PMList.ToArray();
tuesdayPM.DataSource = PMList.ToArray();
wednesdayPM.DataSource = PMList.ToArray();
thursdayPM.DataSource = PMList.ToArray();
fridayPM.DataSource = PMList.ToArray();
loadAccessControl("accesscontrol.json");
dateTimePicker1.AlwaysChooseMonday(dateTimePicker1.Value);
String dateSelected = dateTimePicker1.Value.ToShortDateString();
findManagerForSelectedDate(dateSelected);
}
public void loadAccessControl(String fileName)
{
var accessControlInformation = Environment.CurrentDirectory + Path.DirectorySeparatorChar + fileName;
List<AccessControl> accounts = JsonConvert.DeserializeObject<List<AccessControl>>(File.ReadAllText(accessControlInformation));
foreach (AccessControl account in accounts)
{
Console.WriteLine(account.accountName);
if (account.accountName.ToLower().Contains(Environment.UserName.ToLower()))
{
foreach (CalendarFile file in account.files)
{
// Console.WriteLine(Environment.CurrentDirectory + Path.DirectorySeparatorChar + "content" + Path.DirectorySeparatorChar + file.Filename);
accessToCalendarFilepath.Add(Environment.CurrentDirectory + Path.DirectorySeparatorChar + "content" + Path.DirectorySeparatorChar + file.Filename);
}
break;
}
}
contentsOfFile();
}
private void contentsOfFile()
{
String line;
foreach(var file in accessToCalendarFilepath)
{
StreamReader contentsOfJSONFile = new StreamReader(file);
while((line = contentsOfJSONFile.ReadLine()) != null)
{
if(line.Contains("var "))
{
javaScriptFileContainingJSONObject = javaScriptFileContainingJSONObject + "[";
}
else if(line.Contains("];"))
{
javaScriptFileContainingJSONObject = javaScriptFileContainingJSONObject + "]";
}
else
{
javaScriptFileContainingJSONObject = javaScriptFileContainingJSONObject + line;
}
}
people = JsonConvert.DeserializeObject<List<CalendarModel>>((string)javaScriptFileContainingJSONObject);
managers.Add(people);
javaScriptFileContainingJSONObject = "";
}
}
private void findManagerForSelectedDate(String dateSelected)
{
dateSelected = dateTimePicker1.Value.ToShortDateString();
List<String> managerNames = new List<String>();
foreach(var item in managers)
{
foreach (var subitem in item)
{
CalendarModel c = subitem;
Console.WriteLine(c.date);
c.name = new CultureInfo("en-US", false).TextInfo.ToTitleCase(c.name);
if (userSelection.Count > 0)
{
foreach (var addedUser in userSelection.ToArray())
{
if (!addedUser.Contains(c.name))
{
userSelection.Add(c.name); // CRASHING HERE
//{"Exception of type 'System.OutOfMemoryException' was thrown."}
}
}
}
else
{
userSelection.Add(c.name);
}
}
}
Console.WriteLine();
}
I keep running out of memory.
The CalendarModel class:
namespace Calendar
{
class CalendarModel
{
[JsonProperty("name")]
public string name { get; set; }
[JsonProperty("date")]
public string date { get; set; }
[JsonProperty("title")]
public string title { get; set; }
[JsonProperty("mondayAM")]
public string mondayAM { get; set; }
[JsonProperty("mondayPM")]
public string mondayPM { get; set; }
[JsonProperty("tuesdayAM")]
public string tuesdayAM { get; set; }
[JsonProperty("tuesdayPM")]
public string tuesdayPM { get; set; }
[JsonProperty("wednesdayAM")]
public string wednesdayAM { get; set; }
[JsonProperty("wednesdayPM")]
public string wednesdayPM { get; set; }
[JsonProperty("thursdayAM")]
public string thursdayAM { get; set; }
[JsonProperty("thursdayPM")]
public string thursdayPM { get; set; }
[JsonProperty("fridayAM")]
public string fridayAM { get; set; }
[JsonProperty("fridayPM")]
public string fridayPM { get; set; }
[JsonProperty("saturdayAM")]
public string saturdayAM { get; set; }
[JsonProperty("saturdayPM")]
public string saturdayPM { get; set; }
}
}
I keep crashing at
userSelection.Add(c.name)
Take a close look at what you are doing
foreach (var addedUser in userSelection.ToArray())
{
if (!addedUser.Contains(c.name))
{
userSelection.Add(c.name);
}
}
You are adding to userSelection in the userSelection loop
The test is on !addedUser.Contains
You should not even be able to do that but I think the ToArrray() is letting it happen
So you add Sally
Then then Mark
Then you add Mark again because in the loop Mark != Sally
You are not using List<String> managerNames = new List<String>();
private void findManagerForSelectedDate(String dateSelected)
{
dateSelected = dateTimePicker1.Value.ToShortDateString();
You pass in dateSelected, then overright with dateTimePicker1, and then you don't even use it
Most of you code makes very little sense to me

Deserialize list of objects with list

I have the following XML:
<?xml version="1.0" encoding="utf-8"?>
<CallEvents xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<CallEvent>
<Time>2014-02-24T06:44:27.12</Time>
<Type>Inner</Type>
<Fs>
<StrPair>
<Key>Name</Key>
<Value>Call1</Value>
</StrPair>
<StrPair>
<Key>Owner</Key>
<Value>Ali</Value>
</StrPair>
</Fs>
</CallEvent>
<CallEvent>
<Time>2014-02-24T06:44:29.089</Time>
<Type>Outer</Type>
<Fs>
<StrPair>
<Key>Name</Key>
<Value>Call2</Value>
</StrPair>
<StrPair>
<Key>Id</Key>
<Value>3242</Value>
</StrPair>
<StrPair>
<Key>Another</Key>
<Value>123</Value>
</StrPair>
</Fs>
</CallEvent>
</CallEvents>
I tried to deserialize it, but it doesn't want to deserialize list Fs. I get CallEvents with CallEvent items, and members of CallEvent filled with correct values except list Fs. The list Fs is empty. Why?
What do I do wrong?
class Program
{
static void Main(string[] args)
{
string xmlFile = "call_events.xml";
CallEvents events = CallEvents.OpenFromXmlFile(xmlFile);
Console.ReadKey();
}
}
[Serializable]
public class CallEvent
{
[XmlElement]
public DateTime Time;
[XmlElement]
public CallEventType Type;
public CallEvent()
{
this.Fields = new Dictionary<string, string>();
}
[XmlArray("Fs"), XmlArrayItem("StrPair")]
public List<StrPair> Fs
{
get
{
var list = new List<StrPair>();
foreach (var pair in Fields)
{
list.Add(new StrPair(pair.Key, pair.Value));
}
return list;
}
set
{
Fields.Clear();
foreach (var dictPair in value)
{
Fields.Add(dictPair.Key, dictPair.Value);
}
}
}
[XmlIgnore]
public Dictionary<string, string> Fields;
public void ParseFields(List<LogMessage> eventLogMessages)
{
int eventLogMessagesCount = eventLogMessages.Count;
this.Fields.Clear();
for (int i = 0; i < eventLogMessagesCount; i++)
{
LogMessage logMessage = eventLogMessages[i];
int pos = logMessage.Message.IndexOf(": ");
if(pos == -1)
continue;
string fieldName = logMessage.Message.Substring(0, pos);
pos+=2;
string fieldValue = logMessage.Message.Substring(pos);
if (this.Fields.ContainsKey(fieldName))
{
this.Fields[fieldName] += ("\r\n" + fieldValue);
}
else
{
this.Fields.Add(fieldName, fieldValue);
}
}
}
public override string ToString()
{
StringBuilder sb = new StringBuilder();
sb.AppendFormat("{0} {1} | ", Type, Time);
foreach (var pair in Fields)
{
sb.AppendFormat("{0}: {1}, ", pair.Key, pair.Value);
}
return sb.ToString();
}
[Serializable]
public class StrPair
{
[XmlElement]
public string Key;
[XmlElement]
public string Value;
public StrPair() { }
public StrPair(string key, string value)
{
Key = key;
Value = value;
}
}
}
[XmlRoot("CallEvents")]
public class CallEvents : List<CallEvent>
{
static public CallEvents OpenFromXmlFile(string xmlFileName)
{
CallEvents callEvents;// = new CallEvents();
XmlSerializer ser = new XmlSerializer(typeof(CallEvents));
XmlReader xmlReader = new XmlTextReader(xmlFileName);
try
{
callEvents = (CallEvents)ser.Deserialize(xmlReader);
}
finally
{
xmlReader.Close();
}
return callEvents;
}
public void SaveToXmlFile(string xmlFileName)
{
XmlWriterSettings xmlWriterSettings = new XmlWriterSettings();
xmlWriterSettings.Encoding = System.Text.Encoding.UTF8;
xmlWriterSettings.Indent = true;
XmlSerializer ser = new XmlSerializer(this.GetType());
XmlWriter xmlWriter = null;
tryAgain:
try
{
xmlWriter = XmlTextWriter.Create(xmlFileName, xmlWriterSettings);
ser.Serialize(xmlWriter, this);
}
catch (Exception ex)
{
System.Windows.Forms.DialogResult dr = System.Windows.Forms.MessageBox.Show("Couldn't serialize to XML. Details: " + ex.Message, "Error", System.Windows.Forms.MessageBoxButtons.RetryCancel, System.Windows.Forms.MessageBoxIcon.Warning);
if (dr == System.Windows.Forms.DialogResult.Retry)
{
goto tryAgain;
}
}
finally
{
if (xmlWriter != null)
{
xmlWriter.Close();
}
}
}
}
I havn'e used this in a while so the code might need some touching up.
CallEvents events;
using(XmlReader reader = XmlReader.Create("call_events.xml"))
{
XmlDeserializer deSerializer = new XmlDeserializer(typeof(CallEvents));
events = (CallEvents)deSerializer.Deserialize(reader);
}

How to convert a dictionary pair.value to a dictionary in C#?

i have the following JSON in my application.
string json = #"{""dest"":[ { ""mode"": ""1"", ""test"":""test1,test,test2""},{ ""mode"": ""2"", ""test"": ""test3"" }]}";
To get the value of dest I m using the following method.
var json_serializer = new JavaScriptSerializer();
Dictionary<string, object> dictionary = json_serializer.Deserialize<Dictionary<string, object>>(json);
public Dictionary<string, object> GetObject(Dictionary<string, object> view, string name)
{
Dictionary<string, object> result = new Dictionary<string, object>();
object value = null;
foreach (KeyValuePair<string, object> pair in view)
{
Type type = pair.Value.GetType();
if (pair.Key == name)
{
**Dictionary<string, object> child = (System.Collections.Generic.Dictionary<string, object>)pair.Value;**
result = GetObject(child, name);
if (result != null)
{
break;
}
}
else
{
}
}
return result;
}
I m getting error in the line Dictionary child = (System.Collections.Generic.Dictionary)pair.Value;.
The error says "Unable to cast object of type 'System.Collections.ArrayList' to type 'System.Collections.Generic.Dictionary`2[System.String,System.Object]'."
Anyone knows how to fix this?
Assuming tset in your array is a typo and it actually is test, you can use concerete classes ....
string json = #"{""dest"":[ { ""mode"": ""1"", ""test"":""test1,test,test2""},{ ""mode"": ""2"", ""test"": ""test3"" }]}";
var obj = new JavaScriptSerializer().Deserialize<MyObject>(json);
public class Dest
{
public string mode { get; set; }
public string test { get; set; }
}
public class MyObject
{
public List<Dest> dest { get; set; }
}

Generic List to CSV String

I have a list that I want to write to a CSV string.
The examples I have found all seem to be for single item lists, mine has multiple items.
The code I currently have is;
private static string CreateCSVTextFile<T>(List<T> data, string seperator = ",") where T : ExcelReport, new()
{
var objectType = typeof(T);
var properties = objectType.GetProperties();
var currentRow = 0;
var returnString = "";
foreach (var row in data)
{
var currentColumn = 0;
var lineString = "";
foreach (var info in properties)
{
lineString = lineString + info.GetValue(row, null) + seperator;
currentColumn++;
}
if (seperator != "")
{
lineString = lineString.Substring(0, lineString.Count() - 2);
}
returnString = returnString + Environment.NewLine + lineString;
currentRow++;
}
return returnString;
}
But when the list is large this method takes a very long time to run.
The class my list is based on looks like;
internal class ClientMasterFile
{
public String COL1{ get; set; }
public String COL2{ get; set; }
public String COL3{ get; set; }
public String COL4{ get; set; }
public String COL5{ get; set; }
public String COL6{ get; set; }
public String COL7{ get; set; }
public String COL8{ get; set; }
public String COL9{ get; set; }
public String COL10{ get; set; }
public String COL11{ get; set; }
public String COL12{ get; set; }
}
Is there a faster way to do this using an advanced version of String.Join?
Thanks
Your method can be simplified using StringBuilder and string.Join.
Concatenating strings directly is slow and uses a lot of memory which is fine for small operations.
See: Does StringBuilder use more memory than String concatenation?
private static string CreateCSVTextFile<T>(List<T> data, string seperator = ",")
{
var properties = typeof(T).GetProperties();
var result = new StringBuilder();
foreach (var row in data)
{
var values = properties.Select(p => p.GetValue(row, null));
var line = string.Join(seperator, values);
result.AppendLine(line);
}
return result.ToString();
}
A more complete implementation for CSVs:
private static string CreateCSVTextFile<T>(List<T> data)
{
var properties = typeof(T).GetProperties();
var result = new StringBuilder();
foreach (var row in data)
{
var values = properties.Select(p => p.GetValue(row, null))
.Select(v => StringToCSVCell(Convert.ToString(v)));
var line = string.Join(",", values);
result.AppendLine(line);
}
return result.ToString();
}
private static string StringToCSVCell(string str)
{
bool mustQuote = (str.Contains(",") || str.Contains("\"") || str.Contains("\r") || str.Contains("\n"));
if (mustQuote)
{
StringBuilder sb = new StringBuilder();
sb.Append("\"");
foreach (char nextChar in str)
{
sb.Append(nextChar);
if (nextChar == '"')
sb.Append("\"");
}
sb.Append("\"");
return sb.ToString();
}
return str;
}
Using: escaping tricky string to CSV format
we use linqtocsv with some success
https://linqtocsv.codeplex.com
and here is some explanation
http://www.codeproject.com/Articles/25133/LINQ-to-CSV-library

Categories