11

I am using Newtonsoft.JSON. I won't know the type of object passed to this method, or retrieved to this method, so I am attempting to use DeserializeObject on an object I do not know the type of.

Is this possible? If so, how? Here is my code.

public static List<T> GetObject<T>(string cacheKey, IEnumerable<T> obj)
{
    using (HttpClient client = new HttpClient())
    {
        var response = client.GetAsync("http://localhost:53805/api/NonPersisted/Get/" + cacheKey).Result;

        obj = JsonConvert.DeserializeObject<obj.GetType>(response.Content.ToString());
        return obj.ToList();
    }            
}

I attempted first to use

obj = JsonConvert.DeserializeObject<List<T>>(response.Content.ToString());

This didn't work, obviously, it was unable to parse. Getting the Type of the object won't build, it says obj is a variable but used like a type.

EDIT It appears you can use a generic List<T> without knowing the type with JsonConvert.DeserializeObject<> The real error was that the response.Content was only returning the type. You need to have...

obj = JsonConvert.DeserializeObject<List<T>>(response.Content.ReadAsStringAsync().Result);
13
  • JsonConvert.DeserializeObject<List<T>> didn't work? Commented Jun 14, 2017 at 13:19
  • 1
    How about to use dynamic obj = JsonConvert.DeserializeObject<dynamic>(response.Content); and then access your properties like obj.MyCustomProperty Commented Jun 14, 2017 at 13:21
  • @ChetanRanpariya I know it is always going to be a list, and no I can't cast to a type I don't know. Usually you write JsonConvert.DeserializeObject<SomeObject> and it knows all the properties so it can convert to the Type SomeObject in my case, I can't strongly type the List<T> Commented Jun 14, 2017 at 13:21
  • What happens when you try to do this? Commented Jun 14, 2017 at 13:25
  • by the way, are you sure your API always return a list of objects and not a single object? I don't see a reason why DeserializeObject<List<T>> should not work in your case. Something is wrong with your json structure Commented Jun 14, 2017 at 13:27

4 Answers 4

8

You can make GetObject method generic without having parameter IEnumerable<T> obj.

Following solution I am suggesting with assumption that you know the format of the JSON value being returned from the URL.

For example, that the URL returns JSON which contains array of items and each item has two properties firstName and lastName.

var response = "[{\"firstName\":\"Melanie\",\"lastName\":\"Acevedo\"},
    {\"firstName\":\"Rich\",\"lastName\":\"Garrett\"},
    {\"firstName\":\"Dominguez\",\"lastName\":\"Rose\"},
    {\"firstName\":\"Louisa\",\"lastName\":\"Howell\"},
    {\"firstName\":\"Stone\",\"lastName\":\"Bean\"},
    {\"firstName\":\"Karen\",\"lastName\":\"Buckley\"}]";

I can write GetObject method as following.

public static List<T> GetObject<T>()
{
    var response = "
        [{\"firstName\":\"Melanie\",\"lastName\":\"Acevedo\"},
        {\"firstName\":\"Rich\",\"lastName\":\"Garrett\"},
        {\"firstName\":\"Dominguez\",\"lastName\":\"Rose\"},
        {\"firstName\":\"Louisa\",\"lastName\":\"Howell\"},
        {\"firstName\":\"Stone\",\"lastName\":\"Bean\"},
        {\"firstName\":\"Karen\",\"lastName\":\"Buckley\"}]";

    var obj = JsonConvert.DeserializeObject<List<T>>(response);
        return obj.ToList();
}

Here T in above method can by any type which has properties firstName and lastName. For example

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public DateTime DateOfBirth { get; set; }
}

public class Employee
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public double Salary { get; set; }
}

I can call GetObject method by passing either Person or Employee and get the JSON string deserialize to the collection of objects of these classes as following.

var persons = GetObject<Person>();

foreach (var item in persons)
{
    Console.WriteLine($"{item.FirstName} {item.LastName}");
}

var employees = GetObject<Employee>();

foreach (var item in employees)
{
    Console.WriteLine($"{item.FirstName} {item.LastName}");
}

Overall, the point I am trying to make is if format of the JSON is know the passing appropriate Type to JsonConvert.Deserialize<T> should work without any problem.

If incoming JSON represents a collection and trying to deserialize it to a simple class would fail and vice versa too will not work.

So for your problem, if you know that JSON is going to be a collection then using JsonConvert.Deserialize<List<T>> should not give you any problem as long T has the properties to which values from JSON can be set.

I hope this would help you resolve your issue.

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

1 Comment

I marked this as correct, because it appears you can use JsonConvert.Deserialize<List<T>> There was actually an error in my response Content. I will edit my answer to include the problem
3

I don't think you can call Deserialize<T>(..) if you do not known type T. Only thing I can think of is getting Object:

    public static Object GetObject(string cacheKey)
    {
        using (HttpClient client = new HttpClient())
        {
            var response = client.GetAsync("http://localhost:53805/api/NonPersisted/Get/" + cacheKey).Result;

            var obj = JsonConvert.DeserializeObject(response.Content.ToString());
            return obj;
        }

    }

1 Comment

I think this is going to be the easiest solution. It would have been easier for the developers, but one cast shouldn't kill them!
1

I am not in a position where I can test this right now, but I think the following could work. I have found that JSON.NET does not like List<T> when deserializing, I typically get around this by using arrays instead.

static HttpClient _httpClient = new HttpClient();
public static async Task<T[]> GetObject<T>(string cacheKey)
{
    HttpResponseMessage response = await _httpClient .GetAsync("http://localhost:53805/api/NonPersisted/Get/" + cacheKey);

    return JsonConvert.DeserializeObject<T[]>(response.Content.ToString());
}   

I took the liberty of removing the using statement for HttpClient and made it a static member instead. I also changed the method to run async, you can change it back easily but as I mentioned in my comment you might want to avoid HttpClient and use WebClient instead.

1 Comment

response.Content.ToString() was the problem all along. response.Content.ReadAsStringAsync().Result is the correct way.
0

You can do this by passing the type into the function without strongly typing it. For example:

Type type = obj.GetType();  
JsonConvert.DeserializeObject(json, type);   

1 Comment

This returns object and not what the question wants which is a List<T>

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.