【问题标题】:c# Deserialize json into Listc# 将json反序列化为List
【发布时间】:2015-06-07 14:19:12
【问题描述】:

我有这段代码可以从 API 链接中检索 Json 字符串。 Json 被反序列化并返回到文本框。只要只有 1 个 Json 值,返回的值超过 1 个,它就可以完美地工作,它会因以下错误而崩溃:

附加信息:无法反序列化当前 JSON 数组 (例如[1,2,3])进入类型'GW2_tradingPost.RootObject',因为类型 需要一个 JSON 对象(例如 {"name":"value"})来反序列化 正确。

要修复此错误,请将 JSON 更改为 JSON 对象(例如 {"name":"value"}) 或将反序列化类型更改为数组或 实现集合接口的类型(例如 ICollection、IList) 比如可以从 JSON 数组反序列化的 List。 JsonArrayAttribute 也可以添加到类型中以强制它 从 JSON 数组反序列化。

之所以会发生这种情况,是因为 Json 不是列表,因此无处存放。

我已经尝试过这段代码和各种类似的代码。

List<RootObject> list = JsonConvert.DeserializeObject<List<RootObject>>(jsonReader.ToString());
return list;

这将返回错误:

错误 1 ​​无法隐式转换类型 'System.Collections.Generic.List' 到 'GW2_tradingPost.RootObject' e:\mega\gw2_tradingpost\gw2_tradingpost\api_request.cs 34

我不完全理解它的意思。

这是我的完整代码。

api_Request.cs

public class api_Request
    {
        public RootObject GetApi(string url)
        {

            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);

            try
            {
                WebResponse response = request.GetResponse();
                using (Stream responseStream = response.GetResponseStream())
                {
                 StreamReader reader = new StreamReader(responseStream, Encoding.UTF8);
                var jsonReader = new JsonTextReader(reader);
                var serializer = new JsonSerializer();
                return serializer.Deserialize<RootObject>(jsonReader);
            }
            }
            catch (WebException ex)
            {
                WebResponse errorResponse = ex.Response;
                using (Stream responseStream = errorResponse.GetResponseStream())
                {
                    StreamReader reader = new StreamReader(responseStream, Encoding.GetEncoding("utf-8"));
                    String errorText = reader.ReadToEnd();
                    // log errorText
                }
                throw;
            }
        }

    }


    public class Buy
    {
        public int listings { get; set; }
        public int unit_price { get; set; }
        public int quantity { get; set; }
    }

    public class Sell
    {
        public int listings { get; set; }
        public int unit_price { get; set; }
        public int quantity { get; set; }
    }

    public class RootObject
    {
        public int id { get; set; }
        public List<Buy> buys { get; set; }
        public List<Sell> sells { get; set; }
    }

Form1.cs

 private void button1_Click(object sender, EventArgs e)
        {
            RootObject RootObject = new RootObject();
            api_Request api_Request = new api_Request();
            richTextBox1.Text = api_Request.GetApi("https://api.guildwars2.com/v2/commerce/listings").id.ToString();
        }

在这个 json 中是一个单一的 ID,所以这工作正常。 https://api.guildwars2.com/v2/commerce/listings/19684

但是当检索多个像这里一样的 ID 时,它会中断。 https://api.guildwars2.com/v2/commerce/listings

【问题讨论】:

  • 我们可以看看你试图解析的 json 示例吗?当您尝试反序列化为根对象列表时,但在根对象级别,它正在尝试解析列表,所以我的想法是您有嵌套列表
  • @DavidWatts 我已经编辑了帖子,底部有 2 个 Api 链接,可以显示 Json 的样子。
  • 他们返回完全不同的东西。多个 ID 的链接返回一个整数数组,我猜测这是单个列表的 ID。看起来您必须查询所有列表,然后为每个列表运行另一个列表以获取实际对象。试试看,如果成功我会抛出一个答案,否则我会继续尝试和帮助
  • 如何查询所有列表?查询数据库不相关吗?
  • 当您调用 API 来检索多个 ID 时,将在其末端运行查询。我建议您调用多个 ID 并将其反序列化为一个 int[],然后在完成此操作后,使用 foreach 循环分别为每个 ID 发出请求。这将是大量网络请求的地狱,但如果您在显示中对它们进行分页,则只需针对显示的数量发出请求

标签: c# json list object serialization


【解决方案1】:

这是一个简单的解决方案,可以列出所有 id,但要花很长时间才能完成所有这些

  List<RootObject> rootobject = new List<RootObject>();
    using (var webclient = new WebClient())
    {
        var Ids = webclient.DownloadString(" https://api.guildwars2.com/v2/commerce/listings");
        foreach (var id in Ids.Substring(1, s.Length-2).Split(','))
        {
            string url = string.Format("{0}/{1}","https://api.guildwars2.com/v2/commerce/listings",id);
            var res = webclient.DownloadString(url);
            var jsonObject = JsonConvert.DeserializeObject<RootObject>(res);
            rootobject.Add(jsonObject);
        }


    }

【讨论】:

    【解决方案2】:

    您为多个 ID 提供的链接返回一个整数数组。我建议这样解析:

    var ids = JsonConvert.DeserializeObject<int[]>(jsonReader.ToString())
    

    正如您所说,您的代码适用于单个项目,因此您可以将现有代码用于每个单独的请求,而不是点击 https://api.guildwars2.com/v2/commerce/listings,而是点击 https://api.guildwars2.com/v2/commerce/listings/{id},您可以使用 string.Format() 添加需要的地方。

    认真考虑在int[] 中返回了多少个 id,但您实际上想要获取根对象,从我可以看到它返回的情况来看,您将发出大量请求。

    【讨论】:

      猜你喜欢
      • 2018-10-06
      • 1970-01-01
      • 1970-01-01
      • 2021-06-14
      • 2017-02-28
      • 2014-02-08
      • 1970-01-01
      • 2021-01-14
      • 2018-01-09
      相关资源
      最近更新 更多