【问题标题】:How to generate a JSON class with dynamic name如何生成具有动态名称的 JSON 类
【发布时间】:2021-07-11 05:00:40
【问题描述】:

我不知道该案例是否存在现有名称,但我正在尝试从 NASA API (https://api.nasa.gov/) 检索数据,并且我有一个简单的挑战来捕获地球附近的物体列表。这是我对“https://api.nasa.gov/neo/rest/v1/feed?...”的 GET 请求的 JSON 响应

{
"links": {
    "next": "http://www.neowsapp.com/rest/v1/feed?start_date=2021-07-04&end_date=2021-07-04&detailed=false&api_key=NjgpxgSbYHXyFSBI3HaOhRowtjMZgAKv2t4DMRym",
    "prev": "http://www.neowsapp.com/rest/v1/feed?start_date=2021-07-02&end_date=2021-07-02&detailed=false&api_key=NjgpxgSbYHXyFSBI3HaOhRowtjMZgAKv2t4DMRym",
    "self": "http://www.neowsapp.com/rest/v1/feed?start_date=2021-07-03&end_date=2021-07-03&detailed=false&api_key=NjgpxgSbYHXyFSBI3HaOhRowtjMZgAKv2t4DMRym"
},
"element_count": 6,
"near_earth_objects": {
    "2021-07-03": [
        {
            "links": {
                "self": "http://www.neowsapp.com/rest/v1/neo/3701710?api_key=NjgpxgSbYHXyFSBI3HaOhRowtjMZgAKv2t4DMRym"
            },
            "id": "3701710",
            "neo_reference_id": "3701710",
            "name": "(2014 WF497)",
            "nasa_jpl_url": "http://ssd.jpl.nasa.gov/sbdb.cgi?sstr=3701710",
            "absolute_magnitude_h": 20.23,
            "estimated_diameter": {
                "kilometers": {

}

这就是它在 Visual Studio 中的构建方式(使用 JSON 的特殊粘贴选项)

 public class NearEarthObject
{
    public Links links { get; set; }
    public int element_count { get; set; }
    public Near_Earth_Objects near_earth_objects { get; set; }
}

public class Links
{
    public string next { get; set; }
    public string prev { get; set; }
    public string self { get; set; }
}

public class Near_Earth_Objects
{
    public _20210703[] _20210703 { get; set; }
}

public class _20210703
{
    public Links1 links { get; set; }
    public string id { get; set; }
    public string neo_reference_id { get; set; }
    public string name { get; set; }
    public string nasa_jpl_url { get; set; }
    public float absolute_magnitude_h { get; set; }
    public Estimated_Diameter estimated_diameter { get; set; }
    public bool is_potentially_hazardous_asteroid { get; set; }
    public Close_Approach_Data[] close_approach_data { get; set; }
    public bool is_sentry_object { get; set; }
}

问题是,在元素“near_earth_objects”内部,有一个名为“2021-07-03”的元素(我请求的数据的日期),问题是我试图将它包含到 DataGridView使用 .NET C#(Windows 窗体,但我认为这并不重要)并且用户希望按日期获取信息。所以,“2021-07-03”是一天的有效会员,用户应该可以获取多天的数据。

那么,C# 中是否有一种方法可以在不知道其名称的情况下获取 near_earth_objects 中的所有子对象,因为在我的应用程序中可以选择从日期 X 到 Y 搜索小行星?

【问题讨论】:

  • 您知道该模式将是“YYYY-MM-DD”,因此基于此应该很容易在您的课堂上使用它。只需有一个包含此日期数据数组的“near_earth_objects”类。

标签: c# json .net api


【解决方案1】:

使用 System.Text.Json

API 响应将映射到以下类

public class Neo
{
    public Links Links { get; set; }
    public int ElementCount { get; set; }
    public Dictionary<string, List<NearEarthObject>> NearEarthObjects { get; set; }
}

public class Links
{
    public string Next { get; set; }
    public string Prev { get; set; }
    public string Self { get; set; }
}

public class NearEarthObject
{
    public Links Links { get; set; }
    public string Id { get; set; }
    public string Name { get; set; }
    // Other properties
}

NearEarthObjects 只是一个Dictionary,其中键是格式化的日期,值是包含NearEarthObjectList

PropertyNamingPolicy 将使我们能够支持 API 的 underscore 属性命名约定。

public class UnderscoreNamingPolicy : JsonNamingPolicy
{
    public override string ConvertName(string name)
    {
        return name.Underscore();
    }
}

示例用法

// using using System.Text.Json;
var response = await new HttpClient().GetStringAsync(url);
var neo = JsonSerializer.Deserialize<Neo>(response, new JsonSerializerOptions
{
    PropertyNamingPolicy = new UnderscoreNamingPolicy()
});

foreach(var neos in neo.NearEarthObjects)
{
    Console.WriteLine(neos.Key);
}

【讨论】:

  • 你好,精心制作的豆荚。感谢您的回复,但我无法复制您的代码。我把属性变成了字典,就像你说的那样,但我不能应用第二部分,它得到下划线命名策略。
  • 这就是解决方案。唯一错误的是字典名称应该是“near_earth_objects”,就像它在 JSON 中所说的那样。感谢大家帮助我。
  • @HenriqueSRosa,undercore 方法来自Humanizr 库,您可以将其安装为NuGet package。有alternative 方法可用。
  • @HenriqueSRosa 我也不建议在属性名称中使用下划线,这会使代码难以阅读。见naming guidelines
【解决方案2】:

使用System.Text.JsonJsonNamingPolicy

演示代码

    public class DynamicNamePolicy : JsonNamingPolicy
    {
        public override string ConvertName(string name)
        {
            var today = DateTime.Today.ToString("yyyy-MM-dd");
            if (name.Equals("DateData")) //model property name
                return today; //convert to json string property name
            return name;
        }
    }
//data deserialize
string data = ""; //json string
var obj = JsonSerializer.Deserialize<NearEarthObject>(data, new JsonSerializerOptions
{
     PropertyNamingPolicy = new DynamicNamePolicy(),
});

【讨论】:

  • 您好,文明,感谢您的回复。但我认为这无济于事,因为在某些情况下,我需要从日期 X 到 Y 的所有小行星。所以,我需要 near_earth_objects 内的所有子对象。
  • 好的,所以响应数据是这样的? "near_earth_objects": {"2021-07-03": []},{"2021-07-04": []}
  • 是的,就是这样。抱歉回复晚了。
猜你喜欢
  • 1970-01-01
  • 2018-02-22
  • 1970-01-01
  • 1970-01-01
  • 2019-01-24
  • 2016-03-31
  • 2023-03-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多