-1

I'm trying to convert JSON data from an API to a c# object and I am getting the following error:

The JSON value could not be converted to CountriesDemo.Models.CountryModel. Path: $ | LineNumber: 0 | BytePositionInLine: 1

My function:

public static async Task getCountryData()
{
    var apiURL = "https://restcountries.com/v3.1/alpha/tto";

    HttpClient client = new HttpClient();
    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

    var jsonResults = await client.GetStringAsync(apiURL);
    CountryModel? cshrpObj = System.Text.Json.JsonSerializer.Deserialize< CountryModel >(jsonResults);
    Console.WriteLine(cshrpObj?.name);
}

C# class:

public class CountryModel
{
    public string? name { get; set; }
    public string tld { get; set; } = null!;
    public string cca2 { get; set; } = null!;
    public string ccn3 { get; set; } = null!;
    public string cca3 { get; set; } = null!;
    public string cioc { get; set; } = null!;
    public string currency { get; set; } = null!;
    public string idd { get; set; } = null!;
    public string capital { get; set; } = null!;
    public string altSpellings { get; set; } = null!;
    public string region { get; set; } = null!;
    public string subregion { get; set; } = null!;
    public string languages { get; set; } = null!;
    public string translations { get; set; } = null!;
    public string latlng { get; set; } = null!;
    public string demonym { get; set; } = null!;
    public string landlocked { get; set; } = null!;
    public string borders { get; set; } = null!;
    public string area { get; set; } = null!;
}

Snippet of API data

[
  {
    "name": {
        "common": "United States",
        "official": "United States of America",
        "nativeName": {
            "eng": {
                "official": "United States of America",
                "common": "United States"
            }
        }
    },
    "tld": [
        ".us"
    ],
    "cca2": "US",
    "ccn3": "840",
    "cca3": "USA",
    "cioc": "USA",
    "independent": true,
    "status": "officially-assigned",
    "unMember": true,
]
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
ChrisJ
  • 477
  • 2
  • 15
  • 31

2 Answers2

1

That's because the endpoint you're referring to returns an array of objects, and not directly an object.

Try this:

public static async Task getCountryData()
{
    var apiURL = "https://restcountries.com/v3.1/alpha/tto";

    HttpClient client = new HttpClient();
    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

    var jsonResults = await client.GetStringAsync(apiURL);
    CountryModel[] cshrpObj = System.Text.Json.JsonSerializer.Deserialize<CountryModel[]>(jsonResults);

    Console.WriteLine(cshrpObj.First().name);
}
maxbeaudoin
  • 6,546
  • 5
  • 38
  • 53
  • Thank you for replying so quickly!! Unfortunately., I'm still getting the error Could the issue be with the model?? – ChrisJ Nov 23 '22 at 21:39
  • @ChrisJ the model is not aligned with the JSON schema. `name` is not a string, but a model of its own. Same with `tld`. You're using C# nullables and many required fields are missing in the data. You need to fix you model. Start with a one-to-one representation. – maxbeaudoin Nov 24 '22 at 05:29
  • I'm new to C# so it's a bit confusing!! How can I map some of the keys in the JSON in my model and ignore the rest? – ChrisJ Nov 25 '22 at 18:57
  • See Serge answer for a one-to-one representation. – maxbeaudoin Nov 25 '22 at 19:02
1

unfortunately your json model is not correct. For json you posted you need this model

    List<Country> myDeserializedClass = JsonSerializer.Deserialize<List<Country>>(jsonResults);

public class Country
{
    public Name name { get; set; }
    public List<string> tld { get; set; }
    public string cca2 { get; set; }
    public string ccn3 { get; set; }
    public string cca3 { get; set; }
    public string cioc { get; set; }
    public bool independent { get; set; }
    public string status { get; set; }
    public bool unMember { get; set; }
}
public class Eng
{
    public string official { get; set; }
    public string common { get; set; }
}

public class Name
{
    public string common { get; set; }
    public string official { get; set; }
    public NativeName nativeName { get; set; }
}

public class NativeName
{
    public Eng eng { get; set; }
}

Serge
  • 40,935
  • 4
  • 18
  • 45
  • Thanks for the example!! Why are you making ttd a List and not a string[] – ChrisJ Nov 25 '22 at 19:00
  • @ChrisJ if you want a string array just replace List with string[]. I don't know what are you going to do with this data. In the most cases a list is more usefull. – Serge Nov 25 '22 at 19:13