Dictionary <string,string> map to an object using Automapper
Solution 1
AutoMapper maps between properties of objects and is not supposed to operate in such scenarios. In this case you need Reflection magic. You could cheat by an intermediate serialization:
var data = new Dictionary<string, string>();
data.Add("Name", "Rusi");
data.Add("Age", "23");
var serializer = new JavaScriptSerializer();
var user = serializer.Deserialize<User>(serializer.Serialize(data));
And if you insist on using AutoMapper you could for example do something along the lines of:
Mapper
.CreateMap<Dictionary<string, string>, User>()
.ConvertUsing(x =>
{
var serializer = new JavaScriptSerializer();
return serializer.Deserialize<User>(serializer.Serialize(x));
});
and then:
var data = new Dictionary<string, string>();
data.Add("Name", "Rusi");
data.Add("Age", "23");
var user = Mapper.Map<Dictionary<string, string>, User>(data);
If you need to handle more complex object hierarchies with sub-objects you must ask yourself the following question: Is Dictionary<string, string>
the correct data structure to use in this case?
Solution 2
With the current version of AutoMapper:
public class MyConfig
{
public string Foo { get; set; }
public int Bar { get; set; }
}
var config = new MapperConfiguration(cfg => {});
var mapper = config.CreateMapper();
var source = new Dictionary<string, object>
{
["Foo"] = "Hello",
["Bar"] = 123
};
var obj = mapper.Map<MyConfig>(source);
obj.Foo == "Hello"; // true
Solution 3
This thread is a bit old, but nowadays there's how to do it on automapper without any configuration, as stated at official documentation:
AutoMapper can map to/from dynamic objects without any explicit configuration (...) Similarly you can map straight from Dictionary to objects, AutoMapper will line up the keys with property names.
Update:
The following code shows a working sample (with unit tests).
void Test()
{
var mapper = new MapperConfiguration(cfg => { }).CreateMapper();
var dictionary = new Dictionary<string, object>()
{
{ "Id", 1 },
{ "Description", "test" }
};
var product = mapper.Map<Product>(dictionary);
Assert.IsNotNull(product);
Assert.AreEqual(product.Id, 1);
Assert.AreEqual(product.Description, "test");
}
class Product
{
public int Id { get; set; }
public string Description { get; set; }
}
Solution 4
AutoMapper is quite a flexible solution. You could probably achieve this using a custom mapping profile, e.g.:
public class UserMappingProfile : Profile
{
// Props
public override string ProfileName { get { return "UserMappingProfile"; } }
// Methods
public override void Configure()
{
CreateMap<User, Dictionary<string, string>>().ConvertUsing<DictionaryTypeConverter>();
base.Configure();
}
// Types
internal class DictionaryTypeConverter : ITypeConverter<User, Dictionary<string, string>>
{
public User Convert(ResolutionContext context)
{
var dict = context.SourceValue as Dictionary<string, string>;
if (dict == null)
return null;
return new User() { Name = dict["Name"], Age = dict["Age"] };
}
}
}
With this, I can create a custom instance of a mapper:
var config = new Configuration(new TypeMapFactory(), MapperRegistry.AllMappers());
config.AddProfile<UserMappingProfile>();
config.AssertConfigurationIsValid();
var mapper = new MappingEngine(config);
Which I could probably do:
var dict = new Dictionary<string, string> { { "Name", "Matt" }, { "Age", "27" } };
var user = mapper.Map<User, Dictionary<string, string>>(dict);
Solution 5
Much simpler solution. Just map your object from KeyValuePair. Example:
CreateMap<KeyValuePair<Guid, string>, User>()
.ForMember(u => u.Id, src => src.MapFrom(x => x.Key))
.ForMember(u => u.Name, src => src.MapFrom(x => x.Value));
Related videos on Youtube
Rusi Nova
Updated on April 29, 2022Comments
-
Rusi Nova about 2 years
I have a class like
public User class { public string Name{get;set;} public string Age{get;set; }
With a dictionary like
Dictionary<string,string> data= new Dictionary<string,string>(); data.Add("Name","Rusi"); data.Add("Age","23"); User user= new User();
Now i want to map
User
object to thisdictionary
usingAutomapper
. Automapper maps properties of objects but in my case there is a dictionary and object.How can this be mapped?
-
BoltClock over 12 yearsGo ahead. If you run into any doubts, ask.
-
Rusi Nova over 12 years@boltclock: iam unable to map as automapper maps between objects.
-
turdus-merula over 6 yearsPerhaps this might help: github.com/SlapperAutoMapper/Slapper.AutoMapper.
-
-
EHorodyski over 10 yearsVery good solution, especially if you're using conditionally parsing JSON objects into strong types (such that, say a 'TypeOf' property in a JSON item could fall into one or more object types).
-
Euridice01 over 7 years@Darin using your approach, running into this issue (for solely using first approach): 'System.Collections.Generic.Dictionary
2[[System.Collections.Generic.Dictionary
2+KeyCollection[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, .....,[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]' is not supported for serialization/deserialization of a dictionary, keys must be strings or objects. -
Toolmaker over 4 yearsWhile the docs state that it should work by default, running a somewhat simple test scenario reveals that this is no the case. This will result in a runtime exception:
var mapper = new MapperConfiguration(cfg => { }).CreateMapper(); var result = mapper.Map<Dictionary<String, String>, StringAttribute>(dict);
-
Marcos Jonatan Suriani over 4 yearsThe AutoMapper documentation is just fine. I've just updated my original answer to provide a complete example with unit tests to ensure code works fine too.
-
Minelli about 4 yearsThe solution given by @marcos-jonatan-suriani (below, on Aug 30 '19) is 'native', simpler and updated.
-
Lucian Bargaoanu about 4 yearsAs some of the more recent answers say, it's built in. You don't need the map.
-
Sheegy about 4 yearsIt's built in if your property names are same, what if they are different or if someone need to map one property in dictionary to another, in that case this type of mappers will help. And in case of writing Unit Test cases while mocking the return response, you need to use this kind of mappers to map the data moq response with the actual class object as your data will don't map automatically.
-
Lucian Bargaoanu about 4 yearsYes, but that's not the question here. And in unit tests you should use the exact same mapper/code. So I'm not sure what you're saying.
-
xSx about 2 yearsafter I using this with ForMember it's don't work :(( Or formember or mapping Dictionary. do you know why this might be?