【问题标题】:JSON cannot de-serialize Xamarin weather appJSON 无法反序列化 Xamarin 天气应用程序
【发布时间】:2019-02-10 09:39:19
【问题描述】:

我正在学习如何在 Xamarin 中做列表,我昨天开始了,我有工作要在接下来的几天内完成。我的第一个应用程序运行良好,但第二个应用程序(主要基于第一个应用程序,我有一门课时长为 1:30 并且没有学到很多东西),当我在 Android 上运行我的新程序时,我得到了无法反序列化的错误。

我很确定我的错误在 MainPage.xaml.cs 中

meteo0.cs(第 8 到 26 行)

public class Meteo0
{
    public string precipitaProb { get; set; }
    public int tMin { get; set; }
    public int tMax { get; set; }
    public string predWindDir { get; set; }
    public int idWeatherType { get; set; }
    public int classWindSpeed { get; set; }
    public string longitude { get; set; }
    public int classPrecInt { get; set; }
    public int globalIdLocal { get; set; }
    public string latitude { get; set; }
    public string owner { get; set; }
    public string country { get; set; }
    public string forecastDate { get; set; }
    public List<Meteo0> data { get; set; }
    public DateTime dataUpdate { get; set; }
}

MainPage.xaml.cs(第 10 到 39 行)

public partial class MainPage : ContentPage
{
    const string Url = "https://api.ipma.pt/open-data/forecast/meteorology/cities/daily/1110600";

    public MainPage()
    {
        InitializeComponent();
    }
    protected override void OnAppearing()
    {
        GetMeteo0();
        base.OnAppearing();
    }
    async void GetMeteo0()
    {
        List<Meteo0> meteo0;
        HttpClient httpClient = new HttpClient();
        var content = await httpClient.GetStringAsync(Url);
        meteo0 = JsonConvert.DeserializeObject<List<Meteo0>>(content);
        meteo0ListView.ItemsSource = meteo0;
    }
    private void meteo0ListView_ItemSelected(object sender, SelectedItemChangedEventArgs e)
    {
        Meteo0 meteo0 = e.SelectedItem as Meteo0;
        Navigation.PushAsync(new MeteoDetails(meteo0));
    }
}

编辑的 MainPage.xaml.cs

public partial class MainPage : ContentPage
{
    const string Url = "https://api.ipma.pt/open-data/forecast/meteorology/cities/daily/1110600";

    public MainPage()
    {
        InitializeComponent();
    }
    protected override void OnAppearing()
    {
        GetMeteo0();
        base.OnAppearing();
    }
    async void GetMeteo0()
    {
        List<Meteo0> meteo0;
        HttpClient httpClient = new HttpClient();
        var content = await httpClient.GetStringAsync(Url);
        var result = JsonConvert.DeserializeObject<RootObject>(content);
        meteo0ListView.ItemsSource = result.data;
    }
    private void meteo0ListView_ItemSelected(object sender, SelectedItemChangedEventArgs e)
    {
        Meteo0 meteo0 = e.SelectedItem as Meteo0;
        Navigation.PushAsync(new MeteoDetails(meteo0));
    }
}

编辑过的meteo0.cs

public class Meteo0
{
    public string precipitaProb { get; set; }
    public double tMin { get; set; }
    public double tMax { get; set; }
    public string predWindDir { get; set; }
    public int idWeatherType { get; set; }
    public int classWindSpeed { get; set; }
    public string longitude { get; set; }
    public int classPrecInt { get; set; }
    public int globalIdLocal { get; set; }
    public string latitude { get; set; }
}

新的 RootObject.cs

public class RootObject
{
    public string owner { get; set; }
    public string country { get; set; }
    public string forecastDate { get; set; }
    public List<Meteo0> data { get; set; }
    public DateTime dataUpdate { get; set; }
}

MainPage.xaml

<ListView x:Name="meteo0ListView" ItemSelected="meteo0ListView_ItemSelected">
        <ListView.ItemTemplate>
            <DataTemplate>
                <TextCell Text="Weather"/>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>

【问题讨论】:

  • 实际的错误信息和堆栈跟踪是什么?
  • &lt;TextCell Text="Weather"/&gt; 这是您的数据绑定吗?如果是,你应该使用&lt;TextCell Text="{Binding property}"/&gt;

标签: c# json xamarin xamarin.forms


【解决方案1】:

如果您查看从服务器接收到的 Json 结果,您会发现它实际上并不是根目录中的列表。您正在尝试做的是将单个对象转换为 List,即使数据点列表实际上是根对象中的一个属性。

{  
   "owner":"IPMA",
   "country":"PT",
   "data":[  
      {  
         "precipitaProb":"79.0",
         "tMin":"11.3",
         "tMax":"17.7",
         "predWindDir":"SW",
         "idWeatherType":7,
         "classWindSpeed":2,
         "longitude":"-9.1286",
         "forecastDate":"2019-02-10",
         "classPrecInt":1,
         "latitude":"38.7660"
      },
      {  
         "precipitaProb":"0.0",
         "tMin":"9.6",
         "tMax":"17.0",
         "predWindDir":"N",
         "idWeatherType":1,
         "classWindSpeed":1,
         "longitude":"-9.1286",
         "forecastDate":"2019-02-11",
         "latitude":"38.7660"
      }
      // ...
   ],
   "globalIdLocal":1110600,
   "dataUpdate":"2019-02-10T11:31:03"
}

知道了这一点,您可能应该有两个类,主要的一个包含数据点列表。像这样的:

public class WeatherResult {
    public string owner {get; set; }
    public string country {get; set; }
    public List<Meteo0> data { get; set; }
    // ...
}

然后,您应该反序列化为那个而不是 Meteo0 实体列表。

var result = JsonConvert.DeserializeObject<WeatherResult>(content);

在此之后,您可以通过引用result.data,轻松地将 Meteo0 对象列表用作 ItemsSource。

顺便说一句,从数据中可以看出,tMin 和 tMax 字段不是整数类型,因为它们包含十进制值。你也必须修复那个。

【讨论】:

  • 嗨 hankide,感谢您的快速 awnser,我编辑了我的代码,但我确定我有问题,你能看看编辑后的文件和新的文件吗?谢谢
  • @RuiLima 查看我回答的最后一部分。您应该将 tMin 和 tMax 的类型更改为支持十进制值(浮点、双精度、十进制)而不是整数的类型。否则像 9.6 这样的值的反序列化将失败。
  • 完成了,但我仍然没有得到应用程序上的值,应用程序工作,我可以选择菜单,但我无法获取值
  • 我不确定我是否理解问题所在。您的意思是在将列表绑定到 ItemsSource 后,您无法在 UI 上直观地看到任何内容?如果是这种情况,您还应该在您的问题中发布 MainPage.xaml。否则,您是否使用调试器检查过result.data 是否包含任何项目?
  • 当我启动应用程序时,我有一个可以点击的菜单,然后我会转到提供天气信息的页面,但该信息没有出现,我将在上面发布我的 mainpage.xaml
猜你喜欢
  • 1970-01-01
  • 2019-01-02
  • 2021-05-14
  • 1970-01-01
  • 1970-01-01
  • 2019-08-12
  • 1970-01-01
  • 2021-07-02
相关资源
最近更新 更多