Automapper: Problem mapping from dictionary to object

Created on 8 Aug 2017  路  6Comments  路  Source: AutoMapper/AutoMapper

Example: https://gist.github.com/colin-young/a6fc2dbb5a2d39e4abd0a35600ca59ad Should be able to do dotnet test after getting both files.

Possibly I'm missing something, but according the docs: "Similarly you can map straight from dictionaries to objects, AutoMapper will line up the keys with property names."

So what is it that I'm missing? Am I expecting too much here? I've also tried without generics (e.g. replace T with TestType and change to public class TestClass { ... } with exactly the same results.

There are a number of stackoverflow questions (here, here, here and this newer 2016 post that suggests there may be some issues) where the answer suggests Automapper cannot map from dictionaries, but those are mostly from 2011 and the Automapper documentation appears to suggest otherwise, as does this.

Source/destination types (see gist for full details)

// destination
public class TestType
{
    public string Prop1 { get; set; }
    public string Prop2 { get; set; }
}

// source
new Dictionary<string, string>{
    { "Prop1", prop1 },
    { "Prop2", prop2 }
}

Mapping configuration

Mapper.Initialize(cfg => cfg.CreateMap<Dictionary<string, string>, T>());

Version: 6.1.1

Expected behavior

Expect a fully filled out instance of type T (in this case, TestType)

Actual behavior

Instance of T with all properties null

Steps to reproduce (see gist)

public T GetMappedObject(string prop1, string prop2)
{
    return Mapper.Map<T>(new Dictionary<string, string>{
        { "Prop1", prop1 },
        { "Prop2", prop2 }
    });
}

Most helpful comment

I promise you I really am listening. The issue turns out to be:

Dictionary<string, string>

vs.

Dictionary<string, object>

The latter works, the former doesn't. I updated the documentation page to reflect that.

I actually have a case were I really do want to enforce that all properties are strings. Admittedly it is likely an edge case, but the extra clarity in the docs should be more helpful.

All 6 comments

Just don't create that map :)

The docs look good to me (including the example). It starts with "AutoMapper can map to/from dynamic objects without any explicit configuration:". But feel free to add smth to help the next guy.

So, you're saying that Automapper _doesn't_ support my example? Can you point me to a code sample of mapping from a dictionary to object that _does_ work? Because I thought my example was pretty basic and straightforward.

"Just don't create that map" isn't exactly helpful, and doesn't explain _why_ my example doesn't work.

I've updated my code to this (copy dictionary entries into ExpandoObject and then map that):

public T GetMappedObject(string prop1, string prop2)
{
    var results = new Dictionary<string, string>{
        { "Prop1", prop1 },
        { "Prop2", prop2 }
    };
    var foo = new ExpandoObject();
    foreach(var kvp in results)
    {
        ((IDictionary<string, object>)foo).Add(kvp.Key, kvp.Value);
    }
    return Mapper.Map<T>(foo);
}

Which _does_ work, underscoring the need to determine if Automapper really does support mapping from a dictionary directly. While the docs may start with "AutoMapper can map to/from dynamic objects" they end with "similarly you can map straight from dictionaries to objects, AutoMapper will line up the keys with property names" which, as far as I've been able to determine is not correct. I'm happy to propose some updates to the docs to clarify, but I'd like to understand the expected behavior first.

I promise you I really am listening. The issue turns out to be:

Dictionary<string, string>

vs.

Dictionary<string, object>

The latter works, the former doesn't. I updated the documentation page to reflect that.

I actually have a case were I really do want to enforce that all properties are strings. Admittedly it is likely an edge case, but the extra clarity in the docs should be more helpful.

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

Was this page helpful?
0 / 5 - 0 ratings