How to convert object to Dictionary<TKey, TValue> in C#?
Solution 1
The above answers are all cool. I found it easy to json serialize the object and deserialize as a dictionary.
var json = JsonConvert.SerializeObject(obj);
var dictionary = JsonConvert.DeserializeObject<Dictionary<string, string>>(json);
I don't know how performance is effected but this is much easier to read. You could also wrap it inside a function.
public static Dictionary<string, TValue> ToDictionary<TValue>(object obj)
{
var json = JsonConvert.SerializeObject(obj);
var dictionary = JsonConvert.DeserializeObject<Dictionary<string, TValue>>(json);
return dictionary;
}
Use like so:
var obj = new { foo = 12345, boo = true };
var dictionary = ToDictionary<string>(obj);
Solution 2
I use this helper:
public static class ObjectToDictionaryHelper
{
public static IDictionary<string, object> ToDictionary(this object source)
{
return source.ToDictionary<object>();
}
public static IDictionary<string, T> ToDictionary<T>(this object source)
{
if (source == null)
ThrowExceptionWhenSourceArgumentIsNull();
var dictionary = new Dictionary<string, T>();
foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(source))
AddPropertyToDictionary<T>(property, source, dictionary);
return dictionary;
}
private static void AddPropertyToDictionary<T>(PropertyDescriptor property, object source, Dictionary<string, T> dictionary)
{
object value = property.GetValue(source);
if (IsOfType<T>(value))
dictionary.Add(property.Name, (T)value);
}
private static bool IsOfType<T>(object value)
{
return value is T;
}
private static void ThrowExceptionWhenSourceArgumentIsNull()
{
throw new ArgumentNullException("source", "Unable to convert object to a dictionary. The source object is null.");
}
}
the usage is just to call .ToDictionary()
on an object
Hope it helps.
Solution 3
public static KeyValuePair<object, object > Cast<K, V>(this KeyValuePair<K, V> kvp)
{
return new KeyValuePair<object, object>(kvp.Key, kvp.Value);
}
public static KeyValuePair<T, V> CastFrom<T, V>(Object obj)
{
return (KeyValuePair<T, V>) obj;
}
public static KeyValuePair<object , object > CastFrom(Object obj)
{
var type = obj.GetType();
if (type.IsGenericType)
{
if (type == typeof (KeyValuePair<,>))
{
var key = type.GetProperty("Key");
var value = type.GetProperty("Value");
var keyObj = key.GetValue(obj, null);
var valueObj = value.GetValue(obj, null);
return new KeyValuePair<object, object>(keyObj, valueObj);
}
}
throw new ArgumentException(" ### -> public static KeyValuePair<object , object > CastFrom(Object obj) : Error : obj argument must be KeyValuePair<,>");
}
From the OP:
Instead of converting my whole Dictionary, i decided to keep my obj dynamic the whole time. When i access the keys and values of my Dictionary with a foreach later, i use foreach(dynamic key in obj.Keys) and convert the keys and values to strings simply.
Solution 4
Another option is to use NewtonSoft.JSON.
var dictionary = JObject.FromObject(anObject).ToObject<Dictionary<string, object>>();
Solution 5
this should work:
for numbers, strings, date, etc.:
public static void MyMethod(object obj)
{
if (typeof(IDictionary).IsAssignableFrom(obj.GetType()))
{
IDictionary idict = (IDictionary)obj;
Dictionary<string, string> newDict = new Dictionary<string, string>();
foreach (object key in idict.Keys)
{
newDict.Add(key.ToString(), idict[key].ToString());
}
}
else
{
// My object is not a dictionary
}
}
if your dictionary also contains some other objects:
public static void MyMethod(object obj)
{
if (typeof(IDictionary).IsAssignableFrom(obj.GetType()))
{
IDictionary idict = (IDictionary)obj;
Dictionary<string, string> newDict = new Dictionary<string, string>();
foreach (object key in idict.Keys)
{
newDict.Add(objToString(key), objToString(idict[key]));
}
}
else
{
// My object is not a dictionary
}
}
private static string objToString(object obj)
{
string str = "";
if (obj.GetType().FullName == "System.String")
{
str = (string)obj;
}
else if (obj.GetType().FullName == "test.Testclass")
{
TestClass c = (TestClass)obj;
str = c.Info;
}
return str;
}
![Martin Braun](https://i.stack.imgur.com/bcigi.jpg?s=256&g=1)
Martin Braun
Updated on July 05, 2022Comments
-
Martin Braun about 2 years
How do I convert a dynamic object to a
Dictionary<TKey, TValue>
in C# What can I do?public static void MyMethod(object obj) { if (typeof(IDictionary).IsAssignableFrom(obj.GetType())) { // My object is a dictionary, casting the object: // (Dictionary<string, string>) obj; // causes error ... } else { // My object is not a dictionary } }
-
Martin Braun almost 12 yearsit get an invalid cast exception if obj is a Dictionary<string, int> (doesnt contain any null keys or values). it seems it got problems to cast the number into a string.
-
Martin Braun almost 12 yearsit even throws an invalid cast exception, if i deliver a Dictionary<string, string> on that line. however, thx for the hint, it might be near of my solution.
-
Martin Braun almost 12 yearsmyTypes[0] and myTypes[1] will be always System.Object. it would help alot to track the types of my dictionary, but it doesnt seems to work. i even need to convert the dictionary to <string, string> at the end, however thx.
-
user1519979 almost 12 yearsit was my fault , to get the types you have to do it with idictionary
IDictionary idict = (IDictionary)obj; Type[] myTypes = idict.GetType().GetGenericArguments(); Dictionary<object, object> dict = idict.Cast<dynamic>().ToDictionary(entry => entry.Key, entry => entry.Value);
-
Jeppe Stig Nielsen almost 12 yearsHmm, it's also an ugly solution. Where does
obj
come from? If only we knew that it was always aDictionary<,>
of some kind, we could makeMyMethod
generic, and all would be simple and beautiful. The trouble withIDictionary
is that it could also be aHashtable
or many other types that are non-generic. And theforeach
object type is not even the same (the reason why my answer did not work). -
Martin Braun almost 12 yearsi see, ofc it helps, but its dependent to the given types i pre-code. ive to program independent classes that require to work well with all kinds of types in a Dictionary, even those the programmer creates. Im working on a library I must provide, so.
-
Martin Braun almost 12 yearsobj can be any object, just a number (int), any own class i dont kno, any list that contains classes, or in this case, any Dictionary with any unknown classes. my method already works by delivering a dynamic obj and later to convert it to string to store the dictionary as xml (since XmlSerializer hates Dictionaries). now i got some more trouble and reading it and delivering it back without any errors, i might create a new question then later. thank you.
-
user1519979 almost 12 yearsthe biggest problem i think is that you have to know how to convert an unknown object to a string. maybe you can force programmers to override the ToString() method in their own classes. e.g.:
public abstract class Test { public abstract String ToString(); } class TestClass : Test { public override string ToString() { return "This is a test"; } }
so you can check if the object is a type of the abstract class and then use the tostring method otherwise you will get allways the classname with tostring(not very usefull in my opinion) :) -
dizel3d over 7 yearsThe question is not "How to convert IDictionary objects to IDictionary<T,V>?". The question is "How to convert Object objects to IDictionary<string, Object>?".
-
Simon about 5 years@UserID0908 no worries. BTW i updated it to modern c#
-
David Savage about 5 yearsGreat lateral thinking! I would then put this in an extension: ``` public static class Extensions { public static IDictionary<string, object> ToDictionary( this object o) { var j = JsonConvert.SerializeObject(o); var value = JsonConvert .DeserializeObject<IDictionary<string, object>>(j); return value; } } ```
-
amackay11 almost 5 yearsI went with this approach but discovered it is quite slow so use with caution! My application ground to a snails pace when calling for several hundred dictionaries.
-
Mohaimin Moin almost 4 yearsHow to call MyMethod method from other place?
-
Dmitry Gusarov almost 4 yearsKeep in mind that this approach will convert Int32 to Int64 because JSON don't have strong enough typing and basically have 'number' for everything
-
iBobb over 3 yearsThanks, I also had to filter out 2 of the properties of the object:
var metadata = JObject.FromObject(houseObject).ToObject<Dictionary<string, string>>().Where(x => x.Key != "IsRented" && x.Key != "HasBeenRenovated").ToDictionary(it => it.Key, it => it.Value);
-
Ricardo over 2 yearsNot work with nested objects
-
Auspex about 2 yearsLovely. I was just thinking about this, and my thought was to serialize/deserialize and just googled to see if there was a better way. :)
-
Auspex about 2 yearsEr...
Dictionary<string, string> dicEditdata = obj as Dictionary<string, string>;
, perhaps?