Home > Software engineering >  How to deserialize json object with no parent class?
How to deserialize json object with no parent class?

Time:03-29

I'm trying and failing to write a program that will make an API call and then turn the returned items into objects that fit my model. Specifically I can't make it deserealize, and I suspect it has something to do with how the json is return compared to what my model looks like.

The data I'm trying to get looks like this; https://api.nasa.gov/planetary/apod?start_date=2022-03-01&end_date=2022-03-08&api_key=DEMO_KEY

As you can see, it consists of an array of items, but there is no name for the array items. When I paste this into the Get-model with Paste JSON as Classes, I get this;

public class GetApodItemsResult
{
    public Class1[] Property1 { get; set; }
}

public class Class1
{
    public string copyright { get; set; }
    public string date { get; set; }
    public string explanation { get; set; }
    public string hdurl { get; set; }
    public string media_type { get; set; }
    public string service_version { get; set; }
    public string title { get; set; }
    public string url { get; set; }
}

My entire code works just fine up until I need to serialize the JSON with this line:

var responseObject = await response.Content.ReadFromJsonAsync<GetApodItemsResult>();

, where I get this message; System.Text.Json.JsonException: 'The JSON value could not be converted to UnnamedSpaceProject.Models.GetApodItemsResult.

Interestingly I know that the code works on a spotify api call, so the code really should work largely the same, which leads me to believe that the problem is with how the JSON is formatted. How do I get around that? Because I don't see a way to have the root object contain an unnamed array.

CodePudding user response:

Your GetApodItemsResult class is not a valid class to deserialize the content you get from server, the correct deserialization type will be List<Class1> or Class1[]

var responseObject = await response.Content.ReadFromJsonAsync<List<Class1>>();

I recommend you to use more meaningful name instead of Class1 you can name it Apod (acronym for Astronomy Picture of the Day)

Full working code:

using System.Text.Json;
using System.Text.Json.Serialization;

HttpClient client = new HttpClient();
const string BaseUrl = @"https://api.nasa.gov/";
var response = await client.GetAsync($"{BaseUrl}planetary/apod?start_date=2022-03-01&end_date=2022-03-08&api_key=DEMO_KEY");

if ((response.StatusCode != System.Net.HttpStatusCode.OK))
{
    Console.Error.WriteLine("field to fetch data from server");
}

var responseBody = await response.Content.ReadAsStringAsync();

var pictuersList = JsonSerializer.Deserialize<List<Apod>>(responseBody);

Console.WriteLine($"there is {pictuersList?.Count} apod downloaded successflly");
Console.WriteLine("done");


public class Apod
{
    [JsonPropertyName("copyright")]
    public string Copyright { get; set; } = "";
    [JsonPropertyName("date")]
    public string Date { get; set; } = "";
    [JsonPropertyName("explanation")]
    public string Explanation { get; set; } = "";
    [JsonPropertyName("hdurl")]
    public string Hdurl { get; set; } = "";
    [JsonPropertyName("media_type")]
    public string MediaType { get; set; } = "";
    [JsonPropertyName("service_version")]
    public string ServiceVersion { get; set; } = "";
    [JsonPropertyName("title")]
    public string Title { get; set; } = "";
    [JsonPropertyName("url")]
    public string Url { get; set; } = "";
}

CodePudding user response:

The object your JSON containing is not some container with the array in it, it IS the array. So, the correct code would be like this:

var responseObject = await response.Content.ReadFromJsonAsync<Class1[]>();

The correct JSON for your code would look like this:

{
    "Property1": [{
        "copyright": "Jeff DaiTWAN",
        "date": "2022-03-01",
        "url": "https://apod.nasa.gov/apod/image/2203/DuelingBands_Dai_960.jpg"
    }]
}
  • Related