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.
Related
I would like to merge these two anonymous objects:
var man1 = new {
name = new {
first = "viet"
},
age = 20
};
var man2 = new {
name = new {
last = "vo"
},
address = "123 street"
};
Into a single one:
var man = new {
name = new {
first = "viet",
last = "vo"
},
age = 20,
address = "123 street"
};
I looked for a solution but found nothing clever.
Convert the anonymous object to ExpandoObject which is essentially a dictionary of string key and object value:
var man1Expando = man1.ToDynamic();
var man2Expando = man2.ToDynamic();
public static ExpandoObject ToDynamic(this object obj)
{
IDictionary<string, object> expando = new ExpandoObject();
foreach (var propertyInfo in obj.GetType().GetProperties())
{
var currentValue = propertyInfo.GetValue(obj);
if (propertyInfo.PropertyType.IsAnonymous())
{
expando.Add(propertyInfo.Name, currentValue.ToDynamic());
}
else
{
expando.Add(propertyInfo.Name, currentValue);
}
}
return expando as ExpandoObject;
}
I'm using a helper extension to establish whether a type is an anonymous one:
public static bool IsAnonymous(this Type type)
{
return type.DeclaringType is null
&& type.IsGenericType
&& type.IsSealed
&& type.IsClass
&& type.Name.Contains("Anonymous");
}
Then, merge two resulting expando objects into one, but recursively, checking for nested expando objects:
var result = MergeDictionaries(man1Expando, man2Expando, overwriteTarget: true);
public static IDictionary<string, object> MergeDictionaries(
IDictionary<string, object> targetDictionary,
IDictionary<string, object> sourceDictionary,
bool overwriteTarget)
{
foreach (var pair in sourceDictionary)
{
if (!targetDictionary.ContainsKey(pair.Key))
{
targetDictionary.Add(pair.Key, sourceDictionary[pair.Key]);
}
else
{
if (targetDictionary[pair.Key] is IDictionary<string, object> innerTargetDictionary)
{
if (pair.Value is IDictionary<string, object> innerSourceDictionary)
{
targetDictionary[pair.Key] = MergeDictionaries(
innerTargetDictionary,
innerSourceDictionary,
overwriteTarget);
}
else
{
// What to do when target propety is nested, but source is not?
// Who takes precedence? Target nested property or source value?
if (overwriteTarget)
{
// Replace target dictionary with source value.
targetDictionary[pair.Key] = pair.Value;
}
}
}
else
{
if (pair.Value is IDictionary<string, object> innerSourceDictionary)
{
// What to do when target propety is not nested, but source is?
// Who takes precedence? Target value or source nested value?
if (overwriteTarget)
{
// Replace target value with source dictionary.
targetDictionary[pair.Key] = innerSourceDictionary;
}
}
else
{
// Both target and source are not nested.
// Who takes precedence? Target value or source value?
if (overwriteTarget)
{
// Replace target value with source value.
targetDictionary[pair.Key] = pair.Value;
}
}
}
}
}
return targetDictionary;
}
The overwriteTarget parameter decides which object takes priority when merging.
Usage code:
var man1 = new
{
name = new
{
first = "viet",
},
age = 20,
};
var man2 = new
{
name = new
{
last = "vo",
},
address = "123 street",
};
var man1Expando = man1.ToDynamic();
var man2Expando = man2.ToDynamic();
dynamic result = MergeDictionaries(man1Expando, man2Expando, overwriteTarget: true);
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));
and the result:
{
"name": {
"first": "viet",
"last": "vo"
},
"age": 20,
"address": "123 street"
}
Notice how I assigned the result to dynamic. Leaving compiler assign the type will leave you with expando object presented as IDictionary<string, object>. With a dictionary representation, you cannot access properties in the same manner as if it was an anonymous object:
var result = MergeDictionaries(man1Expando, man2Expando, overwriteTarget: true);
result.name; // ERROR
That's why the dynamic. With dynamic you are losing compile time checking, but have two anonymous objects merged into one. You have to judge for yourself if it suits you.
There's nothing built-in in the C# language to support your use case. Thus, the question in your title needs to be answered with "Sorry, there is no easy way".
I can offer the following alternatives:
Do it manually:
var man = new {
name = new {
first = man1.name.first,
last = man2.name.first
},
age = man1.age,
address = man2.address
};
Use a class instead of an anonymous type for the resulting type (let's call it CompleteMan). Then, you can
create a new instance var man = new CompleteMan(); ,
use reflection to collect the properties and values from your "partial men" (man1 and man2),
assign those values to the properties of your man.
It's "easy" in the sense that the implementation will be fairly straight-forward, but it will still be a lot of code, and you need to take your nested types (name) into account.
If you desperately want to avoid non-anonymous types, you could probably use an empty anonymous target object, but creating this object (var man = new { name = new { first = (string)null, last = (string)null, ...) is not really less work than creating a class in the first place.
Use a dedicated dynamic data structure instead of anonymous C# classes:
The Newtonsoft JSON library supports merging of JSON objects.
Dictionaries can also be merged easily.
ExpandoObjects can be merged easily as well.
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);
Platform: C#
IDE: Visual Studio 2010
I am trying to read all the values from json object and put it in the list of string , for which I am doing Json deserialize but it throws me error...
Here is what I have tried
List<string> lstPName = new List<string>();
JavaScriptSerializer strJsonSer = new JavaScriptSerializer();
localhost.Pstats objStats = new localhost.Pstats();
var strJson = objStats.GetAutoCompleteData(txtSearchBox.Text.Trim());
lstPName = strJsonSer.DeserializeObject<string>(strJson);
Here is what the Json object holds
[{"PlayerName":"WA Mota"},{"PlayerName":"Atif Ahmed"}]
So, I need the player name value to be added in the list...
Simple and straightforward solution:
var strJson = "[{\"PlayerName\":\"WA Mota\"},{\"PlayerName\":\"Atif Ahmed\"}]";
var strJsonSer = new JavaScriptSerializer();
var list = new List<string>();
var result = strJsonSer.DeserializeObject(strJson) as object[];
if (result != null)
{
foreach (Dictionary<string, object> x in result)
{
list.Add(x["PlayerName"].ToString());
}
}
Or, if you are preferring LINQ - you can use instead of foreach loop something like:
list = result
.Cast<Dictionary<string, object>>()
.Select(x => x["PlayerName"].ToString())
.ToList();
Key idea: DeserializeObject used for parsing JSON data like yours gives you array of Dictionary<string, object> where key is JSON property name and value is JSON property value. Size of array equals to objects count in your JSON data.
Using mvc i get values like this to avoid class declarations and router changes.
public dynamic Create([FromBody] dynamic form)
{
var username = form["username"].Value;
var password = form["password"].Value;
var firstname = form["firstname"].Value;
...
I like to iterate through all values and check them for null or empty.
If you get a json from the argument, you could convert it to an Dictionary<string, dynamic> where the string key is the name of the property and the dynamic is a value that can assume any type. For sample:
var d = JsonConvert.DeserializeObject<Dictionary<string, dynamic>>(form);
var username = d["username"];
You also could loop between Keys property from the Dictionary<>:
foreach(var key in d.Keys)
{
// check if the value is not null or empty.
if (!string.IsNullOrEmpty(d[key]))
{
var value = d[key];
// code to do something with
}
}
This is quite old, but I came across this and am wondering why the following was not proposed:
var data = (IDictionary<string, object>)form;
You can use JavaScriptSerializer and dynamic object:
JavaScriptSerializer serializer = new JavaScriptSerializer();
dynamic myDynamicObject = serializer.DeserializeObject(json);
For example, if you want to loop through myDynamicObject["users"]:
foreach (KeyValuePair<string, dynamic> user in myDynamicObject["users"]){
Console.WriteLine(user.Key+": "+user.Value["username"]);
Console.WriteLine(user.Key+": "+user.Value["email"]);
}
In my controller, I get a string that is JSON:
String json_string = this.Request.Content.ReadAsStringAsync().Result;
That looks something like so:
{
"21": {"Id":21,"DisplayOrder":3, ... snip ... },
"333":{"Id":333,"DisplayOrder":2, ... snip ... },
"591":{"Id":591,"DisplayOrder":1, ... snip ... }
}
I don't have a say in the structure of this JSON so can't format it into something without keys. They keys aren't necessary since the ID is within the Value of that Dictionary.
In any case, how do I convert json_string in such a way that allows me to pull out the only two items I want when I iterate over the 'rows' in that structure... Id, DisplayOrder?
Like so:
int Id = row_item.Id;
int DisplayOrder = row_item.DisplayOrder;
Thanks!
Eric
string json = #"{
""21"": {""Id"":21,""DisplayOrder"":3},
""333"":{""Id"":333,""DisplayOrder"":2},
""591"":{""Id"":591,""DisplayOrder"":1}}";
var list = new JavaScriptSerializer()
.Deserialize<Dictionary<string, Dictionary<string, object>>>(json)
.Values
.ToList();
Console.WriteLine(list[0]["Id"]); // <--21
You can also do the same thing with Json.Net
var jObj = JsonConvert
.DeserializeObject<Dictionary<string, Dictionary<string, object>>>(json)
.Values
.ToList();
Console.WriteLine(jObj[0]["Id"]);
dynamic can be utilized too
var jObj = JsonConvert.DeserializeObject<Dictionary<string, dynamic>>(json)
.Values
.ToList();
Console.WriteLine(jObj[0].DisplayOrder);