通用类型JsonConvert.DeserializeObject <list <t>&gt;(string)

时间:2017-06-14 13:16:17

标签: c# generics serialization json.net

我正在使用Newtonsoft.JSON。我不知道传递给这个方法的对象的类型,或者检索到这个方法,所以我试图在一个我不知道它的类型的对象上使用DeserializeObject

这可能吗?如果是这样,怎么样? 这是我的代码。

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();
    }            
}

我首先尝试使用

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

这不起作用,很明显,它无法解析。 获取对象的类型不会构建,它会显示obj is a variable but used like a type

修改 您似乎可以使用通用List<T>而不知道JsonConvert.DeserializeObject<>的类型。真正的错误是response.Content只返回了类型。你需要......

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

4 个答案:

答案 0 :(得分:4)

您可以在不使用参数GetObject的情况下使IEnumerable<T> obj方法通用。

以下解决方案我建议您假设您知道从URL返回的JSON值的格式。

例如,URL返回包含项目数组的JSON,每个项目都有两个属性firstNamelastName

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\"}]";

我可以编写GetObject方法如下。

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();
}

上述方法中的T可以是具有firstNamelastName属性的任何类型。例如

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; }
}

我可以通过传递GetObjectPerson来调用Employee方法,并将JSON字符串反序列化为这些类的对象集合,如下所示。

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}");
}

总的来说,我想说的是,如果JSON的格式知道将JsonConvert.Deserialize<T>传递给适当的类型应该没有任何问题。

如果传入的JSON代表一个集合并且尝试将其反序列化为一个简单的类将失败,反之亦然也将无效。

因此,对于您的问题,如果您知道JSON将成为一个集合,那么使用JsonConvert.Deserialize<List<T>>不应该给您带来任何问题,因为T具有可以设置JSON值的属性

我希望这可以帮助您解决问题。

答案 1 :(得分:1)

我现在无法对此进行测试,但我认为以下内容可行。我发现JSON.NET在反序列化时不喜欢List<T>,我通常会通过使用数组来解决这个问题。

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());
}   

我冒昧地删除了using的{​​{1}}语句,并将其作为静态成员。我还更改了运行HttpClient的方法,您可以轻松地将其更改回来,但正如我在评论中提到的,您可能希望避免使用async并使用WebClient

答案 2 :(得分:0)

如果您不知道类型T,我认为您不能致电Deserialize<T>(..)。 我唯一能想到的就是获取对象:

    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;
        }

    }

答案 3 :(得分:0)

您可以通过将类型传递到函数中而无需强行键入它。 例如:

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