将Json数组反序列化为C#列表对象

12
我尝试将一个来自服务的JSON响应解析为C#观测集合列表对象。该列表对象后来可以用于在XAML页面上展示。 以下是服务的响应:
[
  {
    "orderId": 1,
    "employeeId": "6364",
    "orderTime": 1517583600000,
    "orderCost": 90,
    "comments": null,
    "orderStatus": {
      "orderStatusId": 1,
      "orderStatusName": "Order Placed"
    },
    "orderedItems": [
      {
        "orderItemId": 1,
        "orderQuantity": 1,
        "orderItemCost": 50
      },
      {
        "orderItemId": 2,
        "orderQuantity": 1,
        "orderItemCost": 40
      }
    ]
  },
  {
    "orderId": 2,
    "employeeId": "6364",
    "orderTime": 1517670000000,
    "orderCost": 50,
    "comments": null,
    "orderStatus": {
      "orderStatusId": 3,
      "orderStatusName": "Order Delivered"
    },
    "orderedItems": [
      {
        "orderItemId": 3,
        "orderQuantity": 1,
        "orderItemCost": 50
      }
    ]
  }
]
以下是模型类的代码:
namespace ServiceNew
{

    public class OrderStatus
    {
        public int orderStatusId { get; set; }
        public string orderStatusName { get; set; }
    }

    public class OrderedItem
    {
        [JsonProperty("orderItemId")]
        public int orderItemId { get; set; }

        [JsonProperty("orderQuantity")]
        public int orderQuantity { get; set; }

        [JsonProperty("orderItemCost")]
        public int orderItemCost { get; set; }
    }

    public class Order
    {
        [JsonProperty("orderId")]
        public int orderId { get; set; }

        [JsonProperty("employeeId")]
        public string employeeId { get; set; }

        [JsonProperty("orderTime")]
        public object orderTime { get; set; }
        [JsonProperty("orderCost")]
        public int orderCost { get; set; }

        [JsonProperty("comments")]
        public object comments { get; set; }

        [JsonProperty("orderStatus")]
        public OrderStatus orderStatus { get; set; }

        [JsonProperty("orderedItems")]
        public List<OrderedItem> orderedItems { get; set; }
    }


}

这项服务的运作方式如下:

public  class OrderService
    {
        public OrderService()
        {
            GetJson();
        }
        public async void GetJson()
        {
            if (NetworkCheck.IsInternet())
            {
                var client = new System.Net.Http.HttpClient();
                var response = await client.GetAsync("here is thre URL");
                string orderJson = await response.Content.ReadAsStringAsync(); //Getting response  

                Order ObjOrderList = new Order();
                if (orderJson != " ")
                {

                    Console.WriteLine("response is"+orderJson);

                   //exception occurs here all the time , and I need it to be a list
                    ObjOrderList = JsonConvert.DeserializeObject<Order>(orderJson);
                }

                Console.WriteLine("obj order list is"+ObjOrderList);
            }
        }
    }

在尝试将JSON数组反序列化为C#时做出了一些更改,但我未能成功。现在出现了一个异常,内容为

Newtonsoft.Json.JsonSerializationException: <Timeout exceeded getting exception details>

我卡在这里已经很久了,查遍了StackOverflow和Google,但都没有一个有用的解决方案。

我需要将JSON数据存储到C#对象中,并在XAML页面上以列表的形式再现相同的对象。

先行致谢!


查看 ex.InnerException 是否有任何详细信息。 - jspcal
内部异常没有任何东西。 - shitterpunk
当不用于事件处理程序时,async void 是一种代码异味,构造函数中的长期操作也是一种代码异味。 - Sir Rufo
5个回答

19

我相信异常与你的JSON字符串无关,但请尝试从解决方案文件夹中删除binobj,然后清理并重新构建解决方案。

但是在解决这个问题后,您将获得以下异常:

  

无法将当前JSON数组(例如[1,2,3])反序列化为类型“namespace.Order”,因为该类型需要一个JSON对象(例如{"name":“value”})才能正确反序列化.....

因为您的JSON字符串是Order列表,所以反序列化应该更改为:

List<Order> ObjOrderList = JsonConvert.DeserializeObject<List<Order>>(orderJson);

或者你也可以使用JavaScriptSerializer,例如:

Order[] orderList = new JavaScriptSerializer().Deserialize<Order[]>(orderJson);

小提示:您还可以使用JsonConvert,例如JsonConvert.DeserializeObject<Order[]>(json); - Freggar

4
您正在对订单列表进行反序列化,因此应按以下方式进行反序列化:
...
List<Order> ObjOrderList;
...
ObjOrderList = JsonConvert.DeserializeObject<List<Order>>(orderJson);
...

我已经修改了代码,但仍然存在相同的异常。 - shitterpunk
你的服务代码是原始的还是手动削减的示例? - Sir Rufo
实际上这对我起作用了...今天我改变了代码,它完美地运行了...非常感谢你。 - shitterpunk

2
你的JSON以[开头,以]结尾。这意味着你的JSON表示一个对象数组。这些对象是:

第一个对象

{
    "orderId": 1,
    "employeeId": "6364",
    "orderTime": 1517583600000,
    "orderCost": 90,
    ...
}

第二个对象

{
    "orderId": 2,
    "employeeId": "6364",
    "orderTime": 1517670000000,
    "orderCost": 50,
    ...
}

在你的潜意识中,你知道实际上你的反序列化变量的名称是ObjOrderList(强调List)。
因此,只需将其反序列化为一个Order数组/列表。 < p >使用列表的示例

var ObjOrderList = new List<Order>();
if (orderJson != " ")
{
    //exception occurs here all the time , and I need it to be a list
    ObjOrderList = JsonConvert.DeserializeObject<List<Order>>(orderJson);
}

数组示例

var ObjOrderList = new Order[] { };
if (orderJson != " ")
{
    //exception occurs here all the time , and I need it to be a list
    ObjOrderList = JsonConvert.DeserializeObject<Order[]>(orderJson);
}

谢谢回复,我已经相应地更改了代码,但是出现了Newtonsoft.Json.JsonReaderException: <Timeout exceeded getting exception details> 这个问题,然而我喜欢单词“SUBCONSCIOUS”。 - shitterpunk
我执行了我发布的代码,没有出现任何错误。尝试将你的JSON放入一个变量中,然后再执行你的代码。我将JSON放入一个文件中,并使用以下代码进行读取:string orderJson = File.ReadAllText(@"C:\file.txt");。然后执行你的代码。这可以确保你的问题与输入无关。 - Omar Muscatello
但是我使用的JSON不是来自变量,而是来自服务,所以我无法从文本文件中获取JSON。 - shitterpunk
是的,这只是为了调试。将您的示例JSON(您在问题中发布的JSON)放入文件中并保存。然后使用File.ReadAllText获取文件内容。通过这种方式,您可以了解问题是来自请求响应还是JSON本身(因为对我而言它应该可以工作)。 - Omar Muscatello

1

Try this autogenerated code:

// To parse this JSON data, add NuGet 'Newtonsoft.Json' then do:
//
//    using yourNameSpace;
//
//    var orderResponse = OrderResponse.FromJson(jsonString);

namespace yourNameSpace
{
    using System;
    using System.Collections.Generic;

    using System.Globalization;
    using Newtonsoft.Json;
    using Newtonsoft.Json.Converters;

public partial class OrderResponse
{
    [JsonProperty("orderId")]
    public long OrderId { get; set; }

    [JsonProperty("employeeId")]
    public string EmployeeId { get; set; }

    [JsonProperty("orderTime")]
    public long OrderTime { get; set; }

    [JsonProperty("orderCost")]
    public long OrderCost { get; set; }

    [JsonProperty("comments")]
    public object Comments { get; set; }

    [JsonProperty("orderStatus")]
    public OrderStatus OrderStatus { get; set; }

    [JsonProperty("orderedItems")]
    public List<OrderedItem> OrderedItems { get; set; }
}

public partial class OrderStatus
{
    [JsonProperty("orderStatusId")]
    public long OrderStatusId { get; set; }

    [JsonProperty("orderStatusName")]
    public string OrderStatusName { get; set; }
}

public partial class OrderedItem
{
    [JsonProperty("orderItemId")]
    public long OrderItemId { get; set; }

    [JsonProperty("orderQuantity")]
    public long OrderQuantity { get; set; }

    [JsonProperty("orderItemCost")]
    public long OrderItemCost { get; set; }
}

public partial class OrderResponse
{
    public static List<OrderResponse> FromJson(string json) => JsonConvert.DeserializeObject<List<OrderResponse>>(json);
}

代码是使用QuickType.io生成的。

我舍弃了转换器和其他一些额外的类。如果需要,您可以将Long类型更改为int。

要使用它,只需调用

var orderResponse = OrderResponse.FromJson(jsonString);

将响应传递而不是jsonString。

0
在这段代码中,您可以DeserializeObject JSON文件:
 using (StreamReader r = new StreamReader("D:/Source/ParsijooWeatherApi/ParsijooWeatherApi/cities2.json"))
        {
            string json = r.ReadToEnd();
            List<jsonVariables> items = JsonConvert.DeserializeObject<List<jsonVariables>>(json);

            dynamic array = JsonConvert.DeserializeObject(json);
            foreach (var item in array)
            {
                Console.WriteLine("{0} {1}", item.latitude, item.longitude);
            }
        }

jsonVariables 类是:

public class jsonVariables
{
    [JsonProperty("latitude")]
    public string latitude { get; set; }

    [JsonProperty("longitude")]
    public string longitude { get; set; }

    [JsonProperty("state")]
    public string state { get; set; }
}

在这段代码中,您可以访问根目录项目:

 string _filePath = Path.GetDirectoryName(System.AppDomain.CurrentDomain.BaseDirectory);

然后:

StreamReader r = new StreamReader(_filePath + "/cities2.json"))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接