如何将JSON数组反序列化为C# List对象并在XAML页面展示
解决JSON反序列化异常并在XAML展示订单列表
咱们先揪出你遇到的核心问题:服务返回的JSON是一个Order对象的数组,但你在反序列化的时候却试图转换成单个Order实例,这直接导致了Newtonsoft.Json的序列化异常。除此之外还有几个小问题需要调整,咱们一步步来修复:
1. 修正反序列化的目标类型
你的JSON结构是[{}, {}](数组格式),所以反序列化时要指定List<Order>类型,而不是单个Order。这是引发异常的最关键原因。
2. 调整Order模型的字段类型
orderTime在JSON里是毫秒级时间戳(数字格式),你现在用object类型太宽泛,建议改成long存储,或者直接转换成DateTime(需要加JSON转换器):// 方案1:用long存储时间戳,后续再转成可读DateTime [JsonProperty("orderTime")] public long orderTime { get; set; } // 方案2:直接转DateTime,需引入Newtonsoft.Json的转换器 [JsonProperty("orderTime")] [JsonConverter(typeof(UnixDateTimeConverter))] public DateTime orderTime { get; set; }comments字段如果是字符串类型(可能为null),可以改成string而不是object,更贴合实际业务场景。
3. 修复异步方法的问题
async void仅适合事件处理方法,普通异步方法应该用async Task,否则可能导致异步操作无法正确等待、异常无法捕获等隐性问题。
4. 修正空字符串判断逻辑
原来的if (orderJson != " ")完全不符合预期,应该用!string.IsNullOrWhiteSpace(orderJson)来判断响应内容是否有效。
修正后的完整代码
调整后的模型类
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; } // 用long存储时间戳,新增计算属性转成可读DateTime [JsonProperty("orderTime")] public long orderTime { get; set; } [JsonProperty("orderCost")] public int orderCost { get; set; } // 改成string类型更合理 [JsonProperty("comments")] public string comments { get; set; } [JsonProperty("orderStatus")] public OrderStatus orderStatus { get; set; } [JsonProperty("orderedItems")] public List<OrderedItem> orderedItems { get; set; } // 可选:自动把时间戳转成可读格式 public DateTime OrderTimeDisplay => DateTimeOffset.FromUnixTimeMilliseconds(orderTime).LocalDateTime; } }
修正后的OrderService
public class OrderService { // 把单个Order改成List<Order>存储结果 public List<Order> ObjOrderList { get; set; } public OrderService() { // 注意:构造函数里不要直接调用异步方法,建议在外部通过await调用GetJson // _ = GetJson(); } // 把async void改成async Task,保证异步逻辑可控 public async Task GetJson() { if (NetworkCheck.IsInternet()) { // 使用using自动释放HttpClient资源 using var client = new System.Net.Http.HttpClient(); var response = await client.GetAsync("your-api-url-here"); // 确保请求成功再继续处理 response.EnsureSuccessStatusCode(); string orderJson = await response.Content.ReadAsStringAsync(); if (!string.IsNullOrWhiteSpace(orderJson)) { Console.WriteLine("response is: " + orderJson); // 反序列化成List<Order> ObjOrderList = JsonConvert.DeserializeObject<List<Order>>(orderJson); Console.WriteLine($"obj order list count: {ObjOrderList?.Count ?? 0}"); } } } }
在XAML页面展示订单列表
接下来咱们把订单列表绑定到XAML的ListView控件,实现数据展示:
1. 准备ViewModel(推荐使用)
建议用ViewModel管理数据,实现INotifyPropertyChanged以便数据更新时UI自动刷新:
public class OrdersViewModel : INotifyPropertyChanged { private ObservableCollection<Order> _orders; public ObservableCollection<Order> Orders { get => _orders; set { _orders = value; OnPropertyChanged(); } } private readonly OrderService _orderService; public OrdersViewModel() { _orders = new ObservableCollection<Order>(); _orderService = new OrderService(); LoadOrders(); } private async void LoadOrders() { await _orderService.GetJson(); if (_orderService.ObjOrderList != null) { Orders.Clear(); foreach (var order in _orderService.ObjOrderList) { Orders.Add(order); } } } public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }
2. XAML页面代码
<Page.DataContext> <local:OrdersViewModel /> </Page.DataContext> <ListView ItemsSource="{Binding Orders}"> <ListView.ItemTemplate> <DataTemplate> <StackPanel Margin="10"> <TextBlock Text="Order ID:" FontWeight="Bold"/> <TextBlock Text="{Binding orderId}" Margin="0 0 0 5"/> <TextBlock Text="Status:" FontWeight="Bold"/> <TextBlock Text="{Binding orderStatus.orderStatusName}" Margin="0 0 0 5"/> <TextBlock Text="Total Cost:" FontWeight="Bold"/> <TextBlock Text="{Binding orderCost, StringFormat='${0}'}" Margin="0 0 0 5"/> <TextBlock Text="Order Time:" FontWeight="Bold"/> <TextBlock Text="{Binding OrderTimeDisplay, StringFormat='{0:yyyy-MM-dd HH:mm}'}" Margin="0 0 0 10"/> <!-- 展示订单项详情 --> <TextBlock Text="Items:" FontWeight="Bold"/> <ItemsControl ItemsSource="{Binding orderedItems}"> <ItemsControl.ItemTemplate> <DataTemplate> <StackPanel Orientation="Horizontal" Margin="5 0"> <TextBlock Text="Item ID: "/> <TextBlock Text="{Binding orderItemId}"/> <TextBlock Text=" | Qty: "/> <TextBlock Text="{Binding orderQuantity}"/> <TextBlock Text=" | Cost: $"/> <TextBlock Text="{Binding orderItemCost}"/> </StackPanel> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl> <Border Height="1" Background="Gray" Margin="0 10"/> </StackPanel> </DataTemplate> </ListView.ItemTemplate> </ListView>
这样调整后,你应该能成功完成JSON反序列化,并在XAML页面正常展示订单列表了。
内容的提问来源于stack exchange,提问作者shitterpunk
相关产品推荐
相关产品推荐

