反序列化JSON USGS地震目录API

问题描述

我最近完成了Treehouse在线课程“ C#流和数据处理”,该课程中的一门课程展示了如何使用Webclient查询API并解析返回的数据。所示示例使用Microsoft Bing API检索有关足球运动员的数据,但我试图使用其他API(即USGS地震目录)创建自己的项目。它显示有关最近地震的数据: USGS Earthquake Catalog

我已经使Web客户端正常工作,并且正在获取返回数据。我已经为数据创建了一个新类并将其粘贴为JSON,但是我不确定为什么无法访问代码中的属性? 我想做的是运行一个循环以遍历数据并显示大小,位置和时间。

namespace Earthquakes
{
    class Program
    {
        static void Main(string[] args)
        {
            GetEarthquakes();
        }

        public static void GetEarthquakes()
        {
            var webClient = new WebClient();
            byte[] earthquakeBytes = webClient.DownloadData("https://earthquake.usgs.gov/fdsnws/event/1/query?format=geojson&starttime=2020-08-01&endtime=2020-08-02");
            var serializer = new JsonSerializer();
            using (var stream = new MemoryStream(earthquakeBytes))
            using (var reader = new StreamReader(stream))
            using (var jsonReader = new JsonTextReader(reader))
            {
                string jsonString = "";
                var earthquake = JsonConvert.DeserializeObject<Earthquakes>(jsonString);
                Console.WriteLine(earthquake.Metadata.title);
            }

        }
    }
}

和班级

namespace Earthquakes
{

    public class Metadata
    {
        public long Generated { get; set; }
        public string url { get; set; }
        public string title { get; set; }
        public int status { get; set; }
        public string api { get; set; }
        public int count { get; set; }
    }

    public class Properties
    {
        [JsonProperty("mag")]
        public double Magnitude { get; set; }

        [JsonProperty("place")]
        public string Place { get; set; }
        public object Time { get; set; }
        public object Updated { get; set; }
        public object Tz { get; set; }
        public string Url { get; set; }
        public string Detail { get; set; }
        public int? Felt { get; set; }
        public double? Cdi { get; set; }
        public double? Mmi { get; set; }
        public string Alert { get; set; }
        public string Status { get; set; }
        public int Tsunami { get; set; }
        public int Sig { get; set; }
        public string Net { get; set; }
        public string Code { get; set; }
        public string Ids { get; set; }
        public string Sources { get; set; }
        public string Types { get; set; }
        public int? Nst { get; set; }
        public double? Dmin { get; set; }
        public double Rms { get; set; }
        public double? Gap { get; set; }
        public string MagType { get; set; }
        public string Type { get; set; }
        public string Title { get; set; }
    }

    public class Geometry
    {
        public string type { get; set; }
        public List<double> coordinates { get; set; }
    }

    public class Feature
    {
        public string type { get; set; }
        public Properties properties { get; set; }
        public Geometry geometry { get; set; }
        public string id { get; set; }
    }

    public class Earthquakes
    {
        public string Type { get; set; }
        public Metadata Metadata { get; set; }
        public List<Feature> Features { get; set; }
        public List<double> Bbox { get; set; }
    }

}

解决方法

几点:

  1. 似乎代码中的主要问题是您完全忽略了正在下载的数据,而是反序列化了一个空字符串。实际上,您可以使用DownloadString而不是DownloadData来简化代码。然后,您只需几行代码即可获取JSON并反序列化它:

    webClient.Encoding = Encoding.UTF8;
    var json = webClient.DownloadString("https://earthquake.usgs.gov/fdsnws/event/1/query?format=geojson&starttime=2020-08-01&endtime=2020-08-02");
    var quakes = JsonConvert.DeserializeObject<Earthquakes>(json);
    
  2. 如果您只对几件事感兴趣,则实际上不需要在JSON中包含所有内容的属性。如果您只想要幅度,位置和时间,那么您的模型类可以像这样简单:

    class Earthquakes
    {
        public List<Feature> Features { get; set; }
    }
    
    class Feature
    {
        public Properties Properties { get; set; }
    }
    
    class Properties
    {
        [JsonProperty("mag")]
        public decimal Magnitude { get; set; }
    
        public string Place { get; set; }
    
        [JsonProperty("time")]
        public long TimeMs { get; set; }
    
        public DateTime Time => new DateTime(1970,1,DateTimeKind.Utc).AddMilliseconds(TimeMs);
    }
    

    还要注意,我添加了一种便捷方法,可将time值从JSON转换为可读日期。

  3. 您有一个名为Earthquakes的命名空间和其中的一个类Earthquakes。尽管这在C#中是合法的,但它使代码更难以理解。我建议重命名一个或另一个,以便它们不相同。例如,您可以重命名名称空间EarthquakeDemo或重命名类EarthquakeInfo。当然取决于您。另外,我建议使GetEarthquakes()方法返回它获取的地震,而不是使它无效。然后,您可以将获取逻辑与显示逻辑分开。

这是一个有效的演示,其中应用了以上更改并添加了显示逻辑:https://dotnetfiddle.net/uRg48y

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...