I am using a Database to save Json Structure and Values. Using Testdata the Structure as Dictionary would look similar to this:
Dictionary<string, string> input = new Dictionary<string, string>();
input.Add("application.shortName", "TestShortName");
input.Add("application.longName", "TestLongName");
input.Add("application.description", "TestDescription");
input.Add("application.deepNode.evenDeeperNode", "Values so deep, you can see Adelle rolling");
input.Add("common.yes", "YesTest");
input.Add("common.no", "NoTest");
input.Add("common.save", "SaveTest");
input.Add("common.pager.pagesLenghtBefore", "LengthTestDeepNode");
I never know the names that come from the Database so it could be any name for the key and any depth indicated by a dot something like: "key1.key2.keyN".
Now I want to serialize every key and value I get from the database into Json. With the Testdata from above it would look like this:
{
"application": {
"shortName": "TestShortName",
"longName": "TestLongName",
"description": "TestDescription",
"deepNode": {
"evenDeeperNode": "Values so deep, you can see Adelle rolling"
},
"common": {
"yes": "YesTest",
"no": "NoTest",
"save": "SaveTest",
"pager": {
"pagesLengthBefore": "LengthTestDeepNode"
}
}
}
}
I'm using JSON.NET but I barely scratched the surface and don't know if there is a Method for this. I know I can convert Dictionaries to Json but because of the unknown depth of my keys, that isn't directly possible. I tried to come up with a loop that splits the keys and adds values to the last splitted node, though I was never able to actually program something like that.
I hope this doesn't seem like an inappropriate question but I really need help with this. I appreciate any tips in the right direction. Thanks in advance
Instead of Dictionary you can use dynamic object, like:
var input = new {application = new {shortName = "TestShortName",
longName = "TestLongName"
....},
common = new {yes = "YesTest",
..........}
}
Or using ExpandoObject:
dynamic input = new System.Dynamic.ExpandoObject();
input.application = new System.Dynamic.ExpandoObject();
input.application.shortName = "TestShortName"
input.application.longName = "TestLongName"
.
.
.
input.application.deepNode.evenDeeperNode = "Values so deep, you can see Adelle rolling"
If you need to convert dictionary to json, then following snippet will do it for you:
var input = new Dictionary<string, string>();
input.Add("application.shortName", "TestShortName");
input.Add("application.longName", "TestLongName");
input.Add("application.description", "TestDescription");
input.Add("application.deepNode.evenDeeperNode", "Values so deep, you can see Adelle rolling");
input.Add("common.yes", "YesTest");
input.Add("common.no", "NoTest");
input.Add("common.save", "SaveTest");
input.Add("common.pager.pagesLenghtBefore", "LengthTestDeepNode");
var res = new Dictionary<string, Object>();
foreach(var pair in input)
{
var key = pair.Key;
var parts = key.Split('.');
var currentObj = res;
for (int i = 0; i < parts.Length-1; i++)
{
var property = parts[i];
if (!currentObj.Keys.Contains(property))
currentObj[property] = new Dictionary<string, Object>();
currentObj = (new Dictionary<string, Object>())currentObj[property];
}
currentObj[parts[parts.Length - 1]] = pair.Value;
}
var json = JsonConvert.SerializeObject(res, Formatting.Indented);
Related
Im trying to use the variable OrderBy as an object key.
string OrderBy = "Entity";
output = new object[] { new { OrderBy = "asc" } };
Current output:
"orderBy":[{"OrderBy":"asc" }]
Desired output:
"orderBy":[{"Entity":"asc" }]
This:
output = new object[] { new { OrderBy = "asc" } };
Does not give this:
"orderBy":[{"OrderBy":"asc" }]
As "output". You must be serializing to JSON somehow. The best answer will depend how you are doing that - You can't dynamically set property names in C# (okay, okay, you can with reflection/emit or dynamic), something like this:
dynamic dynamicObject = new ExpandoObject();
(dynamicObject AS IDictionary<String,Object>)[OrderBy] = "asc";
// Then serialize as you are doing now
But that's sketchy and you shouldn't... You should use something like JObject, assuming you are using Newtonsoft.JSON:
JObject jsonObject = new JObject;
jsonObject[Orderby] = "asc"
var output = jsonObject.ToString();
There will be other ways with other serializers, if you say which one you are using...
Dynamic keys can be obtained by using Dictionary. And as you want to have array of them, you need to place them in List<> for example. The code become a little bit messy, but this will give you resluts you want
string OrderBy = "Entity";
var dict = new Dictionary<string, string>();
dict[OrderBy] = "asc";
List<Dictionary<string, string>> list = new List<Dictionary<string, string>>();
list.Add(dict);
var output = new { orderBy = list };
var str = JsonConvert.SerializeObject(output);
Console.WriteLine(str);
You will just have to do it this way:
var output = new object[] { new { Entity = "asc" } };
You can't replace the property name of an anonymous object with a variable, as far as I know.
I am having
Dictionary<String, List<String>> filters = new Dictionary<String, List<String>>();
which is having values like country = us. till now I am able to add it when key is not repeated. now when key country is repeated. it is showing that the key is already present.
what I want is How to add multiple values in the same key. I am not able to do it. Please suggest something.
for (int i = 0; i < msgProperty.Value.Count; i++)
{
FilterValue.Add(msgProperty.Value[i].filterValue.Value);
filterColumn = msgProperty.Value[i].filterColumnName.Value;
filters.Add(filterColumn, FilterValue);
}
what I want
country = US,UK
The different types of all your variables are a bit confusing, which won't help you writing the code. I'm assuming you have a Dictionary<string, List<string>> where the key is a "language" and the value is a list of countries for that language, or whatever. Reducing a problem to a minimal set that reproduces the issue is very helpful when asking for help.
Anyway assuming the above, it's as simple as this:
Try to get the dictionary["somelanguage"] key into existingValue.
If it doesn't exist, add it and store it in the same variable.
Add the List<string> to the dictionary under the "somelanguage" key.
The code will look like this:
private Dictionary<string, List<string>> dictionary;
void AddCountries(string languageKey, List<string> coutriesToAdd)
{
List<string> existingValue = null;
if (!dictionary.TryGetValue(languageKey, out existingValue))
{
// Create if not exists in dictionary
existingValue = dictionary[languageKey] = new List<string>()
}
existingValue.AddRange(coutriesToAdd);
}
You simply need to check whether the value exists in the dictionary, like this:
if (!filters.ContainsKey("country"))
filters["country"] = new List<string>();
filters["country"].AddRange("your value");
Assuming you are trying to add value for key country
List<string> existingValues;
if (filters.TryGetValue(country, out existingValues))
existingValues.Add(value);
else
filters.Add(country, new List<string> { value })
If your values is List<string>
List<string> existingValues;
if (filters.TryGetValue(country, out existingValues))
existingValues.AddRange(values);
else
filters.Add(country, new List<string> { values })
Make use of IDictionary interface.
IDictionary dict = new Dictionary<String, List<String>>();
if (!dict.ContainsKey("key"))
dict["key"] = new List<string>();
filters["key"].Add("value");
I need to get currency values list in C# from here:
http://openexchangerates.org/currencies.json
which produces this kind of output:
{
"AED": "United Arab Emirates Dirham",
"AFN": "Afghan Afghani",
"ALL": "Albanian Lek",
"AMD": "Armenian Dram",
"ANG": "Netherlands Antillean Guilder",
"AOA": "Angolan Kwanza"
// and so on
}
I managed to get a string containing values above using C#, but I cannot find a way to deserialize that string into any custom class or anonymous object, so I am wondering how to do that?
Also, I am trying to use Json.NET to do that, but so far couldn't find a solution...
using Json.Net
var dict = JsonConvert.DeserializeObject<Dictionary<string, string>>(jsonString);
--EDIT--
You can make it shorter
WebClient w = new WebClient();
string url = "http://openexchangerates.org/currencies.json";
var dict = JsonConvert.DeserializeObject<Dictionary<string, string>>(w.DownloadString(url));
A solution using only .Net 4.0 and no third party libraries:
string url = "http://openexchangerates.org/currencies.json";
var client = new System.Net.WebClient();
string curStr = client.DownloadString(url);
var js = new System.Web.Script.Serialization.JavaScriptSerializer();
var res = (js.DeserializeObject(curStr) as Dictionary<string, object>)
.Select(x => new { CurKey = x.Key, Currency = x.Value.ToString() });
Outputs a list of anonymous objects with the keys and values from the list as properties.
Enjoy :)
I've successfully deserialized this JSON string in C#, but can't extract the values from the objects nested in the array:
JavaScriptSerializer js = new JavaScriptSerializer();
string json =
{"key":"1234","status":"ok","members":
[{"id":7,"name":"Joe"},
{"id":2,"name":"Robert"},
{"id":18,"name":"Tim"}
]
}
var d = js.Deserialize < dynamic > (json);
string _key = d["key"]; // this works
Array _members = d["members"]; // this works, length = 3
But I'm having trouble extracting the values out of the objects by name, e.g, this isn't right, but essentially I want
_members[0]["name"] or, _members[0].name
I think the deserializer makes the objects inside the array dictionaries, but I think I'm clearing missing something...
I recommend using Json.NET to do what you're doing. The following code does what you want:
JObject jObject = JObject.Parse(json);
JToken memberName = jObject["members"].First["name"];
Console.WriteLine(memberName); // Joe
Via LINQ to Json.
Update:
var js = new JavaScriptSerializer();
var d = js.Deserialize<dynamic>(json);
Console.WriteLine(d["members"][0]["name"]); // Joe
Also works fine.
It's a bit late for an answer but I've been trying to figure this out and thought I should post somewhere what worked for me.
I wanted to use foreach so:
foreach (var member in json["members"])
{
Console.WriteLine(member["name"]);
}
and by the way, (for some reason like in my project) if you have nested arrays, e.g.
string json =
{"key":"1234","status":"ok",
"members":[
{"items"[
{"id":7,"name":"Joe"},
{"id":2,"name":"Robert"},
{"id":18,"name":"Tim"}
]}
]}
Then:
foreach (var member in json["members"])
{
foreach (var item in member["items"])
{
Console.WriteLine(item["name"]);
}
}
You were quite close in syntax. The key here is that d["members"] is of type Object[] / object[]. Instead of Array, you can use dynamic[] and everything works just fine.
Also note that even this declaration isn't explicitly necessary, as shown in DPeden's updated sample.
Here is the code for your updated snippet (I used a console app to test):
JavaScriptSerializer js = new JavaScriptSerializer();
dynamic d = js.Deserialize<dynamic>(json);
string key = d["key"];
string status = d["status"];
dynamic[] members = d["members"];
Console.WriteLine("key = {0}", key);
Console.WriteLine("status = {0}", status);
Console.WriteLine("members.length = {0}", members.Length);
Console.WriteLine("members type name = {0}", members.GetType().Name);
Console.WriteLine("d[\"members\"] type name = {0}", d["members"].GetType().Name);
And here is additional code showing array and member access.
Console.WriteLine("--");
for (int i = 0; i < members.Length; i++)
{
Console.WriteLine("members[{0}][\"id\"] = {1}", i, members[i]["id"]);
Console.WriteLine("members[{0}][\"name\"] = {1}", i, members[i]["name"]);
}
Console.WriteLine("--");
Console.WriteLine("{0}", d["members"][0]["id"]);
Console.WriteLine("{0}", d["members"][0]["name"]);
Console.ReadKey();
I just want to ask if:
The code below is efficient?
Is there a better way to handle this?
How to code if additional values for tablename/fieldname pair are needed?
We need to use a multi-key dictionary that contains something like (TableName, FieldName, FieldValue).
I searched some answer but the ones I found so far are not applicable to our setup. We are using 3.5 so no Tuple available yet. We are also integrating this script logic with an application that only allows coding "inside" a method body, so we are limited and cannot create a separate class/structure, etc. Our set up is C#/VS 2010.
Any help is appreciated. Thanks in advance!
Dictionary<string, Dictionary<string, string>> tableList = new Dictionary<string, Dictionary<string, string>>();
Dictionary<string, string> fieldList = new Dictionary<string, string>();
// add fields to field list, then add the field lists to the corresponding table list
// clear field list for next table
// values are just hardcoded here to simplify, but is being read from actual objects in the application
fieldList.Add("Field1", "abc");
fieldList.Add("Field2", "def");
fieldList.Add("Field3", "ghi");
fieldList.Add("Field4", "jkl");
tableList.Add("Table1", new Dictionary<string, string>(fieldList));
fieldList.Clear();
fieldList.Add("Field1", "xyz");
fieldList.Add("Field2", "uvw");
fieldList.Add("Field3", "rst");
tableList.Add("Table2", new Dictionary<string, string>(fieldList));
fieldList.Clear();
fieldList.Add("Field1", "123");
fieldList.Add("Field2", "456");
tableList.Add("Table3", new Dictionary<string, string>(fieldList));
fieldList.Clear();
// Display tables and corresponding fields
foreach (KeyValuePair<string, Dictionary<string, string>> fieldList4 in tableList)
{
foreach (KeyValuePair<string, string> fieldList5 in fieldList4.Value)
{
txtMessage.Text = txtMessage.Text + "\r\nTable=" + fieldList4.Key + ", Field=" + fieldList5.Key + " - " + fieldList5.Value;
}
}
// Try to find tables and fields in the lists, and list the value if found
string tableToFind = "Table2";
string fieldToFind = "Field2";
Dictionary<string, string> tableFields = new Dictionary<string, string>();
if (tableList.Keys.Contains(tableToFind) == true)
{
txtMessage.Text = txtMessage.Text = "\r\nTable=" + tableToFind + " exist in table list";
tableList.TryGetValue(tableToFind, out tableFields);
if (tableFields.Keys.Contains(fieldToFind) == true)
{
foreach(KeyValuePair<string, string> fieldData in tableFields)
{
if (fieldData.Key == fieldToFind)
{
txtMessage.Text = txtMessage.Text + "\r\nTable=" + tableToFind + ", Field=" + fieldData.Key +
" with value=" + fieldData.Value + " exist in table list";
break;
}
}
}
}
You can use the compiler to create a composite key for you: Using anonymous types.
var dictionary = new Dictionary<Object, int>();
dictionary.Add(new{Text="A", Number=1}, 1);
dictionary.Add(new{Text="A", Number=2}, 3);
dictionary.Add(new{Text="B", Number=1}, 4);
dictionary.Add(new{Text="B", Number=2}, 5);
var x = dictionary[new{Text="B", Number=2}];
C# will implement Equals and GetHashcode based on your fields. Thus you do get a key which will behave as you would expect.
There's a whole slew of problems and inefficiencies in your code.
If you're going to create multiple dictionaries, create the dictionaries directly. Don't use a separate instance to fill the values and copy from.
Never use string concatenation in a loop like that. Use a StringBuilder or other similar mechanism to build up your strings. You already have your values in a collection so using String.Join() in conjunction with LINQ would clean that up.
Your approach to get values from the dictionary is awkward to say the least. Normally you'd use TryGetValue() alone to attempt to read the key. Your code uses it incorrectly. If you are going to check if the key exists in the dictionary (using Contains()), then there's no point in using TryGetValue(). To make things worse, you did this then searched for the key manually in the inner dictionary by iterating through the key value pairs.
The typical pattern looks like this:
DictValueType value;
if (myDict.TryGetValue(key, out value))
{
// key was in the dictionary, the value is stored in the `value` variable
}
The code you have could be written much much more efficiently like this:
var tableList = new Dictionary<string, Dictionary<string, string>>
{
{ "Table1", new Dictionary<string, string>
{
{ "Field1", "abc" },
{ "Field2", "def" },
{ "Field3", "ghi" },
{ "Field4", "jkl" },
}
},
{ "Table2", new Dictionary<string, string>
{
{ "Field1", "xyz" },
{ "Field2", "uvw" },
{ "Field3", "rst" },
}
},
{ "Table3", new Dictionary<string, string>
{
{ "Field1", "123" },
{ "Field2", "456" },
}
},
};
// Display tables and corresponding fields
txtMessage.Text = String.Join("\r\n",
tableList.SelectMany(table =>
table.Value.Select(fieldList =>
String.Format("Table={0}, Field={1} - {2}",
table.Key, fieldList.Key, fieldList.Value)
)
).ToArray()
);
// (I hope you have this in a separate method)
// Try to find tables and fields in the lists, and list the value if found
string tableToFind = "Table2";
string fieldToFind = "Field2";
var builder = new StringBuilder(txtMessage.Text); // mostly useful if you have a
// lot of different strings to add
Dictionary<string, string> foundTable;
if (tableList.TryGetValue(tableToFind, out foundTable))
{
builder.AppendLine()
.Append("Table=" + tableToFind + " exist in table list");
string foundField;
if (foundTable.TryGetValue(fieldToFind, out foundField))
{
builder.AppendLine()
.AppendFormat("Table={0}, Field={1} with value={2} exist in table list",
tableToFind, fieldToFind, foundField);
}
}
txtMessage.Text = builder.ToString();
Nested dictionaries aren't a bad thing, it's a nice way to organize hierarchies of keys and values. But to keep it maintainable, you generally should encapsulate everything within another class providing methods to manipulate the data without having to manage the dictionaries directly. You can make it both efficient and maintainable. How to implement this is an exercise left to you.
I don't think so many dictionaries would be 'efficient'.
I think the best way would be to add values into the same dictionary multiple times - assuming you want to be able to index them according to one of the indicies (not all):
dictionary.Add("FField1", "xxx");
dictionary.Add("TTable1", "xxx");
Otherwise use a joining character (like '\0') if you want to index them according to all the indicies together.
dictionary.Add("Table1\0Field1", "xxx");