Dynamically deserializing to a property in RestSharp

Chris picture Chris · May 4, 2015 · Viewed 9.3k times · Source

I am playing with the Harvest API and I'm trying to automatically map the entities as easy as possible, unfortunately when I do a request like GET /projects it generates a result like so:

[{
    project: {
        name: "Test"
    }
},
{
    project: {
        name: "Test 2"
}]

In RestSharp, I can't directly do this:

client.Execute<List<Project>>(request)

Because it is going to look for a property called Project. So I have to make another class that has that property, and call it like this:

client.Execute<List<ProjectContainer>>(request)

I don't want to make a 'container' class for every entity, so I thought I found a clever solution to make one class I can use on all:

public class ListContainer<T> where T : IHarvestEntity
{
    public T Item { get; set; }
}

But, of course, the deserializer has no idea it needs to map the entity name (or "Project") to the property Item. In the restsharp documentation I found that I could use [DeserializeAs(Name = "CustomProperty")] to tell the deserializer which field to map to this property. However, attributes do only allow constants, which means I can't do:

[DeserializeAs(Name = typeof(T).FullName)]
public T Item { get; set; }

Does anyone know a clever solution to this? So i don't have to create 10 different container classes?

Answer

Ruard van Elburg picture Ruard van Elburg · May 14, 2015

I suggest you use the XPath equivalent for Json. With Json.NET you can parse the string and create a dynamic object.

With SelectToken you can query values, or using Linq.

The code looks something like this (I did not test it):

// execute the request
RestResponse response = client.Execute(request);
var content = response.Content; // raw content as string

JObject o = JObject.Parse(content);

IList<string> projectNames = o.SelectToken("project").Select(s => (string)s.name).ToList();

You can code the paths or configure the paths anyway you like.

--- Edit ---

Here's an example that I tested, converting the json string to a list of projects.

var projects = JArray.Parse(response.Content).Select(r => new Project(r["project"]["name"].Value<string>())).ToList();