2

Is it possible to create mapping between POCO and JSON field using Automapper?

public class SomeObjectEntity
{
    //JSON
    public string TaskData { get; set; }
    public GUID Id { get; set; }
    public DateTime CreateTime { get; set; }
}

public class SomeObjectModel
{
    public string Name { get; set; }
    public string[] Emails { get; set; }
    public GUID Id { get; set; }
    public DateTime CreateTime { get; set; }
}

In TaskData i have this JSON string:

@"
{
    ""Name"": ""Denis"",
    ""EMails"": [
        ""[email protected]"",
        ""[email protected]""
    ]
}"

Is there any way to create map?

protected override void Configure()
{
    Mapper.CreateMap<SomeObjectEntity, SomeObjectModel>() ...

    Mapper.CreateMap<SomeObjectModel, SomeObjectEntity>() ...
}

Thanks.

9
  • What is supposed to map to what? What are you trying to accomplish? Commented Aug 12, 2014 at 20:22
  • At first I think I need to deserialize Json string and then map deserialized object on model. May be using BeforeMap on Automapper and then work with model and deserialized object? Commented Aug 12, 2014 at 20:30
  • Yes, you have to deserialize it first. Use a library like JSON.NET for that. It's still unclear to me what you are trying to map to what and for what reason, can you elaborate on that? Commented Aug 12, 2014 at 20:31
  • You shouldn't need the mapper.. just do something like SomeObjectModel model = new JavaScriptSerializer().Deserialize<SomeObjectModel>(instanceOfSomeObjectEntity.TaskData); and model will contain your data. Commented Aug 12, 2014 at 20:35
  • 2
    @Denis your comment is completely unreadable.... Commented Aug 12, 2014 at 20:43

2 Answers 2

4

From the code above, I see you want to turn the Name + Emails properties from the SomeObjectModel class and turn these into a JSON string and map this to the SomeObjectEntity.TaskData string property. This can be accomplished using a custom AutoMapper ValueResolver.

public class NameAndEmailResolver : ValueResolver<SomeObjectModel, string>
{
    protected override string ResolveCore(SomeObjectModel source)
    {
        // need a quick and dirty list so we can perform linq query to isolate properties and return an anonymous type
        var list = new List<SomeObjectModel>(){source};
        return JsonConvert.SerializeObject(list.Select(x => new{x.Name, x.Emails});
    }
}

And then call your mapper code:

Mapper.CreateMap<SomeObjectEntity, SomeObjectModel>()
    .ForMember(x => x.TaskData, map => map.ResolveUsing<NameAndEmailResolver>());

This is only for one way binding. You'll have to write the code to go the opposite direction: SomeObjectModel --> SomeObjectEntity.

Sign up to request clarification or add additional context in comments.

2 Comments

One thing that might be helpful to improve this answer a little bit is to use a more descriptive name than x inside the ForMember. Is that source or dest?
Oh gosh. If you go the other way, are you deserializing the JSON once for each property? That seems really inefficient. Know of any way to improve that?
-3

As mentioned by Jeroen, you need to first deserialize your json string to its corresponding type. And to do that, you can use the following. Assuming your type corresponding to the json is T, the following will deserialize it and gives you an object you can use it to map.

private async Task<T> ParseJsonToObjectAsync(string jsonValue)
{
    var obj = await Task.Factory.StartNew(()=>JsonConvert.DeserializeObject<T>(jsonValue);
    return obj;
}

You can also use http://json2csharp.com/ to help you generate the type corresponding your json string. It will save you time. If SomeObjectEntity or TaskData in your description is the object representation of your json string, then that is what T is.

Once you have the json deserialized, you can either manually map or use https://github.com/AutoMapper/AutoMapper

4 Comments

a) It should be ParseJsonToObjectAsync<T>(...) b) Why do you need another Task just to parse json string? What is the threshold value that offsets the cost of creating a new task.
L.B, i didn't get what you are referring in a). for b) its not mandatory to use async but serialize/deserializing can be expensive and in cases like this you might use async to avoid blocking. The general rule of thumb that i know of seems to be 30ms or longer tasks can be a candidate for async. I haven't done any experment myself but i use async for any serializer/deserializer/external service calls including file/db and APIs over the wire.
L.B, its not really another task. I don't know why you thought its another task. Its basically function used to deserialize the json string into the intended object so you can do object to object mapping than playing with string to object mapping. Can you provide your solution please?
json2csharp seems to be out of commision. app.quicktype.io is another site that does the same thing.

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.