Martin Braun
Martin Braun

Reputation: 12569

How to convert object to Dictionary<TKey, TValue> in C#?

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
    }
}

Upvotes: 91

Views: 260498

Answers (19)

christo8989
christo8989

Reputation: 6826

I found it easy to serialize the object into JSON and deserialize as a dictionary with Newtonsoft's Json.NET (using Newtonsoft.Json):

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);

Upvotes: 149

mcemmy
mcemmy

Reputation: 9312

If you don't mind LINQ Expressions;

public static Dictionary<string, object> ConvertFromObjectToDictionary(object arg)
{
     return arg.GetType().GetProperties().ToDictionary(property => property.Name, property => property.GetValue(arg));
}

Upvotes: 16

Al Mubassir Muin
Al Mubassir Muin

Reputation: 438

    string BaseUrl = "http://www.example.com";
    HttpClient client = new HttpClient { BaseAddress = new Uri(BaseUrl) };    
    PropertyInfo[] properties = object.GetType().GetProperties();
    Dictionary<string, string> dictionary = new Dictionary<string, string>();
    foreach (PropertyInfo property in properties)
    {
      dictionary.Add(property.Name, property.GetValue(model, null).ToString());
    }
               
    foreach (string key in dictionary.Keys)
    {
      client.DefaultRequestHeaders.Add(key, dictionary[key]);
    }

Upvotes: 0

cartory
cartory

Reputation: 31

I hope this could work :)

    //  obj = new { a = "string", b = 0, c = true };
    static Dictionary<string, object> ToDictionary(object obj)
    {
        int i = 0;
        var props = obj.GetType().GetProperties();
        return props.ToDictionary(k => props[i].Name, v => props[i++].GetValue(obj));
    }

Upvotes: 2

Fatih Temizer
Fatih Temizer

Reputation: 11

This way for object array to Dictionary<string, object> List coverting

object[] a = new object[2];
var x = a.Select(f => (Dictionary<string, object>)f).ToList();

This way for single object to Dictionary<string, object> coverting

object a = new object;
var x = (Dictionary<string, object>)a;

Upvotes: 1

Mahib
Mahib

Reputation: 4063

I've done something like this and works for me.

using System.ComponentModel;

var dictionary = new Dictionary<string, string>();

foreach (var propDesc in TypeDescriptor.GetProperties(Obj))
{
    if (!string.IsNullOrEmpty(propDesc.GetValue(Obj)))
    {
        dictionary.Add(propDesc.Name, propDesc.GetValue(Obj));
    }
}

Also, another alternative and innovative solution is here.

var dictionary = new System.Web.Routing.RouteValueDictionary(Obj);

Upvotes: 2

Bigtoe
Bigtoe

Reputation: 3510

Another option is to use NewtonSoft.JSON.

var dictionary = JObject.FromObject(anObject).ToObject<Dictionary<string, object>>();

Upvotes: 24

Davoud
Davoud

Reputation: 17

You can use this:

Dictionary<object,object> mydic = ((IEnumerable)obj).Cast<object>().ToList().ToDictionary(px => px.GetType().GetProperty("Key").GetValue(px), pv => pv.GetType().GetProperty("Value").GetValue(pv));

Upvotes: 0

Simon
Simon

Reputation: 34830

Assuming key can only be a string but value can be anything try this

public static Dictionary<TKey, TValue> MyMethod<TKey, TValue>(object obj)
{
    if (obj is Dictionary<TKey, TValue> stringDictionary)
    {
        return stringDictionary;
    }

    if (obj is IDictionary baseDictionary)
    {
        var dictionary = new Dictionary<TKey, TValue>();
        foreach (DictionaryEntry keyValue in baseDictionary)
        {
            if (!(keyValue.Value is TValue))
            {
                // value is not TKey. perhaps throw an exception
                return null;
            }
            if (!(keyValue.Key is TKey))
            {
                // value is not TValue. perhaps throw an exception
                return null;
            }

            dictionary.Add((TKey)keyValue.Key, (TValue)keyValue.Value);
        }
        return dictionary;
    }
    // object is not a dictionary. perhaps throw an exception
    return null;
}

Upvotes: 3

Antonio Leonardo
Antonio Leonardo

Reputation: 1862

This code securely works to convert Object to Dictionary (having as premise that the source object comes from a Dictionary):

    private static Dictionary<TKey, TValue> ObjectToDictionary<TKey, TValue>(object source)
    {
        Dictionary<TKey, TValue> result = new Dictionary<TKey, TValue>();

        TKey[] keys = { };
        TValue[] values = { };

        bool outLoopingKeys = false, outLoopingValues = false;

        foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(source))
        {
            object value = property.GetValue(source);
            if (value is Dictionary<TKey, TValue>.KeyCollection)
            {
                keys = ((Dictionary<TKey, TValue>.KeyCollection)value).ToArray();
                outLoopingKeys = true;
            }
            if (value is Dictionary<TKey, TValue>.ValueCollection)
            {
                values = ((Dictionary<TKey, TValue>.ValueCollection)value).ToArray();
                outLoopingValues = true;
            }
            if(outLoopingKeys & outLoopingValues)
            {
                break;
            }
        }

        for (int i = 0; i < keys.Length; i++)
        {
            result.Add(keys[i], values[i]);
        }

        return result;
    }

Upvotes: 1

T.Todua
T.Todua

Reputation: 56341

I use this simple method:

public Dictionary<string, string> objToDict(XYZ.ObjectCollection objs) {
    var dict = new Dictionary<string, string>();
    foreach (KeyValuePair<string, string> each in objs){
        dict.Add(each.Key, each.Value);
    }
    return dict;
}

Upvotes: 0

Ehsan Sajjad
Ehsan Sajjad

Reputation: 62488

You can create a generic extension method and then use it on the object like:

public static class Extensions
{
    public static KeyValuePair<TKey, TValue> ToKeyValuePair<TKey, TValue>(this Object obj)
    {
        // if obj is null throws exception
        Contract.Requires(obj != null);

        // gets the type of the obj parameter
        var type = obj.GetType();
        // checks if obj is of type KeyValuePair
        if (type.IsGenericType && type == typeof(KeyValuePair<TKey, TValue>))
        {

            return new KeyValuePair<TKey, TValue>(
                                                    (TKey)type.GetProperty("Key").GetValue(obj, null), 
                                                    (TValue)type.GetProperty("Value").GetValue(obj, null)
                                                 );

        }
        // if obj type does not match KeyValuePair throw exception
        throw new ArgumentException($"obj argument must be of type KeyValuePair<{typeof(TKey).FullName},{typeof(TValue).FullName}>");   
 }

and usage would be like:

KeyValuePair<string,long> kvp = obj.ToKeyValuePair<string,long>();

Upvotes: 0

MiBol
MiBol

Reputation: 2125

Simple way:

public IDictionary<T, V> toDictionary<T, V>(Object objAttached)
{
    var dicCurrent = new Dictionary<T, V>();
    foreach (DictionaryEntry dicData in (objAttached as IDictionary))
    {
        dicCurrent.Add((T)dicData.Key, (V)dicData.Value);
    }
    return dicCurrent;
}

Upvotes: -3

Lijin Durairaj
Lijin Durairaj

Reputation: 5222

   public static void MyMethod(object obj){
   Dictionary<string, string> dicEditdata = data as Dictionary<string, string>;
   string abc=dicEditdata["id"].ToString();} 

suppose--- if you place the cursor over the object(obj) while debugging and if you get an object with the value {['id':'ID1003']} then you can use the value as

string abc=dicEditdata["id"].ToString(); 

Upvotes: 3

Zakari
Zakari

Reputation: 733

object parsedData = se.Deserialize(reader);
System.Collections.IEnumerable stksEnum = parsedData as System.Collections.IEnumerable;

then will be able to enumerate it!

Upvotes: -1

d.popov
d.popov

Reputation: 4255

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.

Upvotes: 58

cuongvn_it
cuongvn_it

Reputation: 251

    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.

Upvotes: 25

user1519979
user1519979

Reputation: 1874

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;
    }

Upvotes: 7

Jeppe Stig Nielsen
Jeppe Stig Nielsen

Reputation: 61912

As I understand it, you're not sure what the keys and values are, but you want to convert them into strings?

Maybe this can work:

public static void MyMethod(object obj)
{
  var iDict = obj as IDictionary;
  if (iDict != null)
  {
    var dictStrStr = iDict.Cast<DictionaryEntry>()
      .ToDictionary(de => de.Key.ToString(), de => de.Value.ToString());

    // use your dictStrStr        
  }
  else
  {
    // My object is not an IDictionary
  }
}

Upvotes: -1

Related Questions