简体   繁体   中英

How to generate a JSON class with dynamic name

I don't know if there is an existing name for that case, but I'm trying to retrieve data from NASA API ( https://api.nasa.gov/ ) and I have a simple challenge to catch a list of objects near earth. Here is the JSON response I have from the GET request I do to "https://api.nasa.gov/neo/rest/v1/feed?...."

{
"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": {

}

And that's the way it is built in Visual Studio (using the Special Paste option for 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; }
}

The question is, inside of the element "near_earth_objects", there is an element called "2021-07-03" (the date of the data I requested), the problem is that I am trying to include it into a DataGridView made in .NET C# (Windows Forms, but that doesn't matters here, I think) and the user wants to get the information by date. So, "2021-07-03" is a valid member just for one day, and the user should be able to get data from multiple days.

So, is there a way in C# to get all child objects inside of near_earth_objects without knowing their names since there will be the option to search for asteroids from date X to Y in my application?

use System.Text.Json , JsonNamingPolicy

demo code

    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(),
});

Using System.Text.Json

The API response will map to the following classes

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
}

The NearEarthObjects is simply a Dictionary , where the key is the formatted date and value is a List containing NearEarthObject

The PropertyNamingPolicy will allow us to support the API's underscore property naming convention.

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

Example usage

// 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);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM