【问题标题】:Generic Type JsonConvert.DeserializeObject<List<T>>(string)通用类型 JsonConvert.DeserializeObject<List<T>>(string)
【发布时间】:2017-11-16 16:12:58
【问题描述】:

我正在使用 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&lt;List&lt;T&gt;&gt;(response.Content.ToString());

这不起作用,显然,它无法解析。 获取对象的类型不会生成,它说obj is a variable but used like a type

编辑 看来您可以在不知道 JsonConvert.DeserializeObject&lt;&gt; 类型的情况下使用通用 List&lt;T&gt; 真正的错误是 response.Content 仅返回类型。你需要...

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

【问题讨论】:

  • JsonConvert.DeserializeObject> 不起作用?
  • 如何使用动态obj = JsonConvert.DeserializeObject&lt;dynamic&gt;(response.Content);,然后访问您的属性,例如obj.MyCustomProperty
  • @ChetanRanpariya 我知道它总是一个列表,不,我不能转换为我不知道的类型。通常你写JsonConvert.DeserializeObject&lt;SomeObject&gt;,它知道所有的属性,所以它可以转换为类型SomeObject,在我的例子中,我不能强类型List&lt;T&gt;
  • 当你尝试这样做时会发生什么?
  • 顺便问一下,您确定您的 API 总是返回对象列表而不是单个对象吗?我看不出 DeserializeObject> 在您的情况下不应该起作用的原因。你的 json 结构有问题

标签: c# generics serialization json.net


【解决方案1】:

您可以使GetObject 方法通用而无需参数IEnumerable&lt;T&gt; 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; }
}

我可以通过传递PersonEmployee 来调用GetObject 方法,并将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&lt;T&gt; 应该没有任何问题。

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

所以对于您的问题,如果您知道 JSON 将成为一个集合,那么使用 JsonConvert.Deserialize&lt;List&lt;T&gt;&gt; 应该不会给您带来任何问题,只要 T 具有可以设置来自 JSON 的值的属性。

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

【讨论】:

  • 我将此标记为正确,因为您似乎可以使用JsonConvert.Deserialize&lt;List&lt;T&gt;&gt; 我的响应内容中实际上有一个错误。我将编辑我的答案以包含问题
【解决方案2】:

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

    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】:

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

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

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

【讨论】:

  • response.Content.ToString() 一直是问题所在。 response.Content.ReadAsStringAsync().Result 是正确的方法。
【解决方案4】:

您可以通过将类型传递给函数来完成此操作,而无需强类型化。 例如:

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

【讨论】:

  • 这会返回对象,而不是问题想要的 List
猜你喜欢
  • 2017-03-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-04
  • 1970-01-01
  • 1970-01-01
  • 2019-06-26
  • 2021-07-06
相关资源
最近更新 更多