I am trying to send a key-pair based array object using ajax, here array is created dynamically
["{\"key\":\"#c1\",\"value\":\"g1\"}","{\"key\":\"#c1\",\"value\":\"g2\"}", "{\"key\":\"#c2\",\"value\":\"g3\"}", "{\"key\":\"#c4\",\"value\":\"g4\"}"]
Above is json formatted data which i am sending to a method and able to receive it. At c# end Dictionary<string, string> Columns is used. problem here is that the key values are just number and values contain each element of above mentioned json data as shown below,
foreach(var eachVals in columns)
{
string k = eachVals.Key;
string col = eachVals.Value;
}
when iterating the dictionary eachVals.key is array index (0,1,...) and eachVals.Value contains {"key":"#c1","value":"g1"}
So what i want is separate keys i.e "#c1","#c1","#c2"... and values i.e "g1","g2"...
You would need to deserialize the values from col. Using Newtonsoft.Json, would look something like this:
Dictionary<string, string> columns = new Dictionary<string, string>
{
{ #"0", #"{""key"": ""#c1"", ""value"":""g1"" }" },
{ #"1", #"{""key"": ""#c2"", ""value"":""g2"" }" }
};
var result = columns.ToDictionary(
column => JsonConvert.DeserializeObject<MyObj>(column.Value).key,
column => JsonConvert.DeserializeObject<MyObj>(column.Value).value);
Where MyObj is:
internal class MyObj
{
public string key { get; set; }
public string value { get; set; }
}
I think you can do or get the idea from this:
foreach(var eachVals in columns)
{
var e = eachVals.Value.Split(',');
e = e[0].Split(':');
string k = e[0];
string v = e[1];
}
Related
I am creating a library for an existing API. I currently have QueryParameter classes for each request class. The QueryParameter classes are simple but they do vary (not all requests take the same query parameters).
Here is an example of a QueryParameter class:
public class ApiRequestAQueryParameters
{
public string Name { get; set; }
public int Start { get; set; }
public int Stop { get; set; }
}
I am interested in a way to convert a class like this into a Dictionary that I can feed to our Web client. I am hoping to have a reusable method like:
private Dictionary<string, string> GenerateQueryParameters(object queryParametersObject)
{
// perform conversion
}
This way I won't have to pull out the QueryParameter properties for each request (there will be dozens of requests)
The reason that I am using QueryParameter classes instead of making QueryParameter a Dictionary property of each API request class is to be developer friendly. I want to make it so that others can build these API requests by looking at the classes.
There are 2 ways: 1) use reflection and 2) serialize to json and back.
Here is the 1st method:
private Dictionary<string, string> GenerateQueryParameters(object queryParametersObject)
{
var res = new Dictionary<string, string>();
var props = queryParametersObject.GetType().GetProperties();
foreach (var prop in props)
{
res[prop.Name] = prop.GetValue(queryParametersObject).ToString();
}
return res;
}
You can do something like this:
private Dictionary<string, string> GenerateQueryParameters(object queryParameters)
{
var startStop = new StartStop() { Start = queryParameters.Start, Stop = queryParameters.Stop};
var result = new Dictionary<string, string>();
result.Add(queryParameters.Name, startStop);
return result;
}
public class StartStop
{
public int Start { get; set; }
public int Stop { get; set; }
}
This may be the perfect case to utilize ExpandoObjects. An ExpandoObject is a dynamic type, whose properties can be created at run time. ExpandoObject implements IDictionary < string, object > so it's easy to convert to a Dictionary < string, object > .
In the example below, an ExpandoObject is created and converted to a Dictionary < string, object > and then converted to a Dictionary < string, string >.
dynamic apiVar = new ExpandoObject();
apiVar.Name = "Test";
apiVar.Start = 1;
apiVar.Stop = 2;
var iDict = (IDictionary<string, object>) apiVar;
/* if you can utilize a Dictionary<string, object> */
var objectDict = iDict.ToDictionary(i => i.Key, i => i.Value);
/* if you need a Dictionary<string, string> */
var stringDict = iDict.ToDictionary( i=>i.Key, i=> i.Value.ToString());
There are also different ways of setting properties on an ExpandoObject. Below is an example of setting a property by a variable name.
dynamic apiVar = new ExpandoObject();
var propertyName = "Name";
apiVar[propertyName] = "Test";
propertyName = "Start";
apiVar[propertyName] = 1;
propertyName = "Stop";
apiVar[propertyName] = 2;
I always reuse the RouteValueDictionary class for this. It has a constructor that accepts any object and the class itself implements IDictionary.
It's available in the System.Web dll
private Dictionary<string, string> GenerateQueryParameters(object queryParametersObject)
{
return new RouteValueDictionary(queryParametersObject).ToDictionary(d => d.Key, d => Convert.ToString(d.Value));
}
I received some help here with the following LINQ query, but am still struggling with it. The result I'm trying to obtain is to display some attributes and their values from an xml file in a DataGridView control. I'm calling my method from a button click and am trying to pass back the list for display in the grid. Here is an example of the row:
<z:row CenterCode="JAX" CenterName="Jacksonville" Version="1.0" NextExport="66742" NextImport="29756" LastImportTime="2015-06-10T14:48:33" FtpProxyServer="" FtpUserName="" FtpPassword="" ResetImportID="False"/>
Here is the method:
public static List<string[]> MonitorCounts(string upperLimit)
{
// Load xml
XDocument xmldoc = XDocument.Load(#"c:\XML\Configuration.xml");
XNamespace z = "#RowsetSchema";
Int32 limit = Convert.ToInt32(upperLimit);
var elementQuery = xmldoc.Descendants(z + "row").Where(e => (long?)e.Attribute("NextExport") > limit | (long?)e.Attribute("NextImport") > limit);
var attributes = elementQuery.Select(e => e.Attributes().Select(a => new KeyValuePair<string, string>(a.Name.LocalName, (string)a)).ToList()).ToList();
return attributes;
}
My questions are how to select only specific attributes and values in attributes. If I do something like this:
var attributes = elementQuery.Select(e => e.Attributes("CenterName").Select(a => new KeyValuePair<string, string>(a.Name.LocalName, (string)a)).ToList()).ToList();
then this is returned:
[0] = {[CenterName, Jacksonville]}
I need to select this and 4 others. I'm also getting a convrsion error - Cannot implicitly convert type 'System.Collections.Generic.List<System.Collections.Generic.List<System.Collections.Generic.KeyValuePair<string,string>>>' to 'System.Collections.Generic.List<string[]>. Appreciate any pointers to help me along.
You can use an anonymous type:
var attributes =
elementQuery.Select(e => new
{
CenterName = (string)e.Attribute["CenterName"],
Version = (string)e.Attribute["Version"],
// more attributes
}).ToList();
You can't however return this from the method in a useful way. So if you really need both the attribute name and the attribute value as strings, try this approach instead:
var attributes =
elementQuery.Select(e => new []
{
Tuple.Create("CenterName", (string)e.Attribute["CenterName"]),
Tuple.Create("Version", (string)e.Attribute["Version"]),
// more attributes
}).SelectMany(x => x).ToList();
The return type of your method now has to be List<Tuple<string, string>>.
And finally, if you actually need a List<string[]> as the return type, use this code:
var attributes =
elementQuery.Select(e => new []
{
new [] { "CenterName", (string)e.Attribute["CenterName"] },
new [] { "Version", (string)e.Attribute["Version"] },
// more attributes
}).SelectMany(x => x).ToList();
I solved my own problem. Here is what I did:
Created a class for the attributes needed:
public class dataRow
{
public string CenterName { get; set; }
public string CenterCode { get; set; }
public string NextImport { get; set; }
public string NextExport { get; set; }
public string LastImportTime { get; set; }
}
Selected the results into it:
List<dataRow> dataRows = elementQuery.Select( e => new dataRow
{ CenterName = (string)e.Attribute("CenterName"),
CenterCode = (string)e.Attribute("CenterCode"),
NextImport = (string)e.Attribute("NextImport"),
NextExport = (string)e.Attribute("NextExport"),
LastImportTime = (string)e.Attribute("LastImportTime") }).ToList();
Changed my method to return the correct object:
public static List<dataRow> MonitorCounts(string upperLimit)
Set my grids datasource to the method return:
dataGridView1.DataSource = xmlProcessing.MonitorCounts(tbxUpperLimit.Text.ToString());
return dataRows;
I want to use a foreach k, v pairs loop to run through a multidimensional list, and output those values elsewhere. Here is the code:
public class LogTable
{
public string FunctionName { get; set; }
public string LogTime { get; set; }
}
public class TableVars
{
public List<LogTable> loggingTable { get; set; }
public TableVars()
{
loggingTable = new List<LogTable>();
}
public void createLogList()
{
loggingTable = new List<LogTable>();
}
}
foreach( KeyValuePair<string, string> kvp in tablevars.loggingTable)
{
// output would go here. I haven't looked it up yet but I assume it's something
// along the lines of var = k var2 = v? Please correct me if I'm wrong.
}
When I run my mouse over 'foreach' I get a warning saying - 'Cannot convert type 'DataObjects.LogTable' to 'System.Collections.Generic.KeyValuePair. How can I resolve this issue, or is there a more efficient way to accomplish the same goal?
Thanks!
I should have added more context, sorry. I'm trying to return the two different values inside the properties 'FunctionName' and 'LogTime' which I have added via:
var tablevars = new TableVars();
tablevars.loggingTable.Add(new LogTable { FunctionName = errorvalue, LogTime = logtime });
To specify more accurately, the intention of the foreach k, v loop was to grab every distinct property of FunctionName and LogTime and input them into a database in SQL Server. This is why the distinction between k, v (or FunctionName, LogTime) is important. Again, please correct me if I'm wrong.
You cannot use KeyValuePair<>, because you don't enumerate a Dictionary<>. But you don't need to, simply do this:
foreach(LogTable logTable in tablevars.loggingTable)
{
// do whatever with logTable.FunctionName and logTable.LogTime
}
Either change your foreach to iterate through List<LogTable>
foreach( LogTable lt in tablevars.loggingTable)
{...}
OR
Use a KeyValuePair instead of creating class LogTable
public class TableVars
{
public Dictionary<string,string> loggingTable { get; set; }
public TableVars()
{
loggingTable = new Dictionary<string,string>();
}
public void createLogList()
{
loggingTable = new Dictionary<string, string>();
}
}
foreach( KeyValuePair<string, string> kvp in tablevars.loggingTable)
{
//loggingTagle is now a KeyValuePair
}
I have the following text that I need to put into a dictionary. At first sight I thought that it would be very easy but at the end I found myself doing extensive string search and finding sometimes values that break the parser.
"0":
{
"key":"valueWithAnyCharInside",
"key2":"valueWithAnyCharInside",
"key3":"valueWithAnyCharInside"
},
This will map into the following model:
class Item
{
private int id;
private Dictionary<string, string> data;
}
Any ideas? Maybe using regex ...
Your data format is probably a JSON, but you gave only a part of it. I've modified it slightly as:
{"0":
{
"key":"valueWithAnyCharInside",
"key2":"valueWithAnyCharInside",
"key3":"valueWithAnyCharInside"
}
}
now you can parse it as following:
string json = ...; //your json goes here
var serializer = new JavaScriptSerializer();
var parsed = serializer.Deserialize<Dictionary<string, Dictionary<string, string>>>(json);
//printing data
parsed["0"].Select(pair => string.Format( "{0} - {1}", pair.Key, pair.Value))
.ToList()
.ForEach(Console.WriteLine);
prints:
key - valueWithAnyCharInside
key2 - valueWithAnyCharInside
key3 - valueWithAnyCharInside
To get strongly typed List<Item> use next code
List<Item> items = parsed.Select(pair => new Item { Id = int.Parse(pair.Key),
Data = pair.Value})
.ToList();
Where Item is :
class Item
{
public int Id { get; set; }
public Dictionary<string, string> Data {get;set;}
}
I have an object that I obtained from an xml file and it contains a field of SeriesCode and ProductCodes associated with the specified Series code.
i.e.
SeriesCodeA
prodCode1
prodCode2
prodCode3
SeriesCodeA
prodCode4
prodCode5
prodCode6
I created a the following dictionary
Dictionary<string, List<string>> dictSeries = new Dictionary<string, List<string>>();
The values from the object I want to add to the dictionary. So in other words I want to, for each series code added to the Dictionary key as a string value add the corresponding product codes as string values.
something like
foreach (var s in series)
{
string code = s.SeriesCode;
if (dictSeries.ContainsKey(code))
{
foreach (var l in s.ProductCodes)
{
dictSeries[code].Add(l);
}
}
}
The above is not quite right
How can I add the SeriesCodes as keys to the dictionary with the corresponding product codes as string values(List)?
Use LINQ and ToDictionary method to make it more readable:
var dictSeries = series.ToDictionary(x => x.SeriesCode, x => x.ProductCodes);
A assumed your Series class looks like that:
class Serie
{
public string SeriesCode { get; set; }
public List<string> ProductCodes { get; set; }
}
Your code also will work, but needs few improvements:
foreach (var s in series)
{
string code = s.SeriesCode;
if (!dictSeries.ContainsKey(code))
{
dictSeries.Add(code, new List<string>());
}
foreach (var l in s.ProductCodes)
{
dictSeries[code].Add(l);
}
}