6

What would be the best way to deserialize this

Dictionary<string, object>{
   {"fName", "John"},
   {"lName", "Doe"},
   {"email", "[email protected]"}
}

to this

class Member{
   string fName;
   string lName;
   string email;
}

6 Answers 6

6

NewtonSoft has become so common in ASP.NET applications these days that if I needed a short and sweet solution to this type of mapping I could use some code like this. Sure it might be abusive to introduce a third party library if its not already present, but sometimes we just use what works. And Newtonsoft does!

using Newtonsoft.Json;
class SerializationTests
{
    public void DictionarySerializeSample()
    {

        var dict = new Dictionary<string, object>
        {
            {"fName", "John"},
            {"lName", "Doe"},
            {"email", "[email protected]"}
        };

        string dictInJson = JsonConvert.SerializeObject(dict);
        var member = JsonConvert.DeserializeObject<Member>(dictInJson);

        // use Newtonsoft to write out the object re-serialized
        Console.WriteLine(JsonConvert.SerializeObject(member, Formatting.Indented));

    }

    public class Member
    {
        public string fName;
        public string lName;
        public string email;
    }
}
Sign up to request clarification or add additional context in comments.

Comments

2

This isn't really serialization in the normal sense, that usually refers to taking some disk or network formatted data (binary, ASCII, JSON etc) and loading it into a runtime object.

However, if I understand you correctly, I think what you are trying to do is...

public Member( Dictionary<string,object> dictionary )
{ 
    fName = dictionary["fName"];
    lName = dictionary["lName"];
    email = dictionary["email"];
}

// usage Member m = new Member( inputDictionary );

5 Comments

I was thinking about that, but I don't like the idea of hard-coding any values. That's why I am asking about the best way, if there is any avoiding this approach. Simply I was looking for something like this Member member = (Member)myDictionary;
I would put it in a constructor for Member that takes a dictionary as a parameter. Adding to answer...
If you want to avoid the hard coded key values, then I would use a reflection based technique like @KiethS offered
@negative: so the items are always going to be 3? or could be more? like fName, lName, email, and Address, for instance.
@KMan, yes, it will be more, Member class is given as an example.
2

If the structure is static:

return new Member 
{
   fName = myDictionary["fName"], 
   lName = myDictionary["lName"], 
   email = myDictionary["email"]
};

If the structure is not known at design time:

public static T Hydrate<T>(this Dictionary<string, string> theDictionary, 
   T myObject = new T()) where T:new() //default/optional parameter is valid in 4.0 only
{

   //var myObject = myObject ?? new T(); //alternative in 3.5 and previous

   foreach(string key in myDictionary.Keys)
   {
      var propInfo = typeof(T).GetProperty(key);

      if(propInfo == null) throw new ArgumentException("key does not exist");
      propInfo.SetValue(myObject, theDictionary[key], null);
   }
   return myObject;
}

1 Comment

I think there must something wrong with my class, because typeof(T).GetProperty(key) is always null and typeof(T).GetProperties() is empty. Same as typeof(Member).GetProperties()
2

This isn't serialization, it's conversion. If you really want it convertible, then make it convertible. Implement TypeConverter.

Example code

using System;

using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; using System.Xml.Linq; using System.Diagnostics; using System.Xml.Serialization; using System.ComponentModel; using System.Globalization;

namespace ConsoleApplication1 {

internal class MemberConverter : TypeConverter
{
    public override bool CanConvertFrom(ITypeDescriptorContext context,
  Type sourceType)
    {
        if (sourceType == typeof(Dictionary<string, object>))
        {
            return true;
        }
        return base.CanConvertFrom(context, sourceType);
    }

    public override object ConvertFrom(ITypeDescriptorContext context,
  CultureInfo culture, object value)
    {
        if (value is Dictionary<string, object>)
        {
            Member member = new Member();
            Dictionary<string, object> d = (Dictionary<string, object>)value;
            if (d.ContainsKey("fName")) { member.fName = Convert.ToString(d["fName"]); };
            if (d.ContainsKey("lName")) { member.lName = Convert.ToString(d["lName"]); };
            if (d.ContainsKey("email")) { member.email = Convert.ToString(d["email"]); };
            return member;
        }
        return base.ConvertFrom(context, culture, value);
    }

    public override object ConvertTo(ITypeDescriptorContext context,
  CultureInfo culture, object value, Type destinationType)
    {
        if (destinationType == typeof(Dictionary<string, object>))
        {
            Member member = (Member)value;
            Dictionary<string, object> d = new Dictionary<string, object>();
            d.Add("fName", member.fName);
            d.Add("lName", member.lName);
            d.Add("email", member.email);
            return d;
        }
        return base.ConvertTo(context, culture, value, destinationType);
    }

}

[TypeConverter(typeof(MemberConverter))]
internal class Member
{
    public string fName;
    public string lName;
    public string email;
}

class Program
{
    static void Main(string[] args)
    {
        var d = new Dictionary<string, object> {
           {"fName", "John"},
           {"lName", "Doe"},
           {"email", "[email protected]"}
        };

        Member m = (Member)TypeDescriptor.GetConverter(typeof(Member)).ConvertFrom(d);

        Debugger.Break();
    }
}

}

Comments

0

One approach that seems to make sense would be to have a static helper function for this.

public static Member Create(Dictionary<string, object inputs)
{
    Member oNew = new Member();
    oNew.fName = inputs["fName"].ToString();
    // etc
    return oNew;
}

Comments

0

You could also use reflection to this, it could be a lot of code depending on the objects you're actually using, but it would be a lot more flexible. This probably isn't a complete sample, but it gets you the general idea.

public T InstantiateFromDictionary<T>(Dictionary<string, object> values) where T : new()
{
   Type t = typeof(T);
   T instance = new T();
   foreach(KeyValuePair<string, object> kvp in values)
   {
        PropertyInfo prop = t.GetProperty(kvp.Key);
        prop.SetValue(instance, kvp.Value, null);
   }

   return instance;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.