3

I have a dynamic object (actually, a JObject, from JSON.NET) being built dynamically from JSON. I want to have its properties copied to an existing object. The properties from the dynamic object should exist in the target object's type, if not, it's ok to have an error. I am looking at Automapper, latest version, for this. I tried to create a map from JObject to the proper type, but I don't think it'll work because the properties in the JObject are stored in an internal dictionary. Is this possible at all?

Ricardo Peres
  • 13,724
  • 5
  • 57
  • 74

1 Answers1

10

Yes, this is possible.

If you already have a JObject, then you don't really need Automapper to copy the properties from it to your existing target object. The Json.Net serializer provides a Populate() method which will do this. You can create an extension method to make it easy to call right from the JObject:

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

public static class JsonExtensions
{
    public static void PopulateObject<T>(this JToken jt, T target)
    {
        JsonSerializer serializer = new JsonSerializer();
        serializer.Populate(jt.CreateReader(), target);
    }
}

Then, whenever you need to copy the properties you can do this:

jObj.PopulateObject<Foo>(existingFoo);

Note: if your variable that holds the JObject is declared as dynamic then you'll have to cast it so the runtime binder can find the extension method:

((JObject)jObj).PopulateObject<Foo>(existingFoo);

Here is a quick demo to prove the concept: https://dotnetfiddle.net/dhPDCj

If you would still prefer to use Automapper, you can configure it to do this same conversion instead of its usual member-based mapping. The trick is to use the ConvertUsing method when setting up the mapping:

Mapper.Initialize(cfg => cfg.CreateMap<JObject, Foo>().ConvertUsing((jo, foo) =>
{
    JsonSerializer serializer = new JsonSerializer();
    serializer.Populate(jo.CreateReader(), foo);
    return foo;
}));

Then use this code to copy the properties:

Mapper.Map<JObject, Foo>(jObj, existingFoo);
Brian Rogers
  • 125,747
  • 31
  • 299
  • 300
  • No... I explicitly said I wated to copy tje properties to an *existing* object! – Ricardo Peres Jul 16 '16 at 19:21
  • Sorry, I somehow missed that detail in your question. I've updated my answer. – Brian Rogers Jul 16 '16 at 23:48
  • @BrianRogers You had indicated: The Json.Net serializer provides a PopulateObject() method... but really they provide the Populate() method. Your answer is still clear, but it is a little misleading. – Tim Friesen Oct 28 '19 at 16:31
  • Actually it looks like newtonsoft have added their own PopulateObject method: Newtonsoft.Json.JsonConvert.PopulateObject(string value, object target) – Tim Friesen Oct 28 '19 at 16:39
  • 1
    @TimFriesen You're right; I had the wrong method name in the text of the answer; although the code example was correct. I fixed it and added a link to the documentation. `JsonSerializer` has `Populate`; `JsonConvert` has `PopulateObject`. The difference is in the parameters they accept. The former is what we need here since it accepts a `JsonReader`, which can be created from the `JObject`. The latter is used when you are starting from a JSON string. – Brian Rogers Oct 28 '19 at 17:02