Home > Mobile >  Convert complex JSON to C# Model and downloading Data
Convert complex JSON to C# Model and downloading Data

Time:09-06

I'm trying to convert a data from a nested JSon file to C# Model, and I get this error :

Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[convert_json_to_model.Fields]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.

To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.
Path 'nhits', line 1, position 9.

Here is some data

{
"nhits":17933,
"parameters":{
"dataset":[
"osm-fr-bars@babel"
],
"rows":3,
"start":0,
"format":"json",
"timezone":"UTC"
},
"records":[
{
"datasetid":"osm-fr-bars@babel",
"recordid":"d95394fd7d34aa34aa9b236661bce9cda534a8ab",
"fields":{
"other_tags":"{\"cuisine\": \"tapas\", \"ref:FR:CRTA\": \"RESAQU047V506W6V\", 
\"capacity\": \"14\", \"description\": \"Tous les jours \u00e0 partir de 7h\", 
\"source\": \"BDOrtho IGN; Cadastre M\u00e0J 2015; Sirtaqui\", \"outdoor_seating\": 
\"yes\", \"source:ref:FR:CRTA\": \"Sirtaqui\"}",
"name":"Au boin coin",
"geo_point_2d":[
  44.0549704,
  0.2603921
],
"phone":" 33 5 53 65 67 45"  
},
"geometry":{
"type":"Point",
"coordinates":[
 0.2603921,
 44.0549704
 ] 
 }

Here is the link of my Json file to see all fields : https://data.opendatasoft.com/api/records/1.0/search/?dataset=osm-fr-bars@babel&rows=30

Here is my model after using the tool JSON to C#

public class Fields
{
    [JsonProperty("other_tags")]
    public string OtherTags { get; set; }

    [JsonProperty("name")]
    public string Name { get; set; }

    [JsonProperty("geo_point_2d")]
    public List<double> GeoPoint2d { get; set; }

    [JsonProperty("phone")]
    public string Phone { get; set; }
}

public class Geometry
{
    [JsonProperty("type")]
    public string Type { get; set; }

    [JsonProperty("coordinates")]
    public List<double> Coordinates { get; set; }
}

public class Record
{
    [JsonProperty("datasetid")]
    public string Datasetid { get; set; }

    [JsonProperty("recordid")]
    public string Recordid { get; set; }

    [JsonProperty("fields")]
    public Fields Fields { get; set; }

    [JsonProperty("geometry")]
    public Geometry Geometry { get; set; }
}

public class Root
{
    [JsonProperty("records")]
    public List<Record> Records { get; set; }
}

Here is the method to deserialize

    static async Task Main(string[] args)
    {

        string url = "https://data.opendatasoft.com/api/records/1.0/search/?dataset=osm-fr-bars@babel&rows=30";

        HttpClient httpClient = new HttpClient();

        try
        {
            var httpResponseMessage = await httpClient.GetAsync(url); 
            string jsonResponse = await httpResponseMessage.Content.ReadAsStringAsync();
          
           
           List<Fields> myBars = JsonConvert.DeserializeObject<List<Fields>>(jsonResponse);
          
            foreach (var bar in myBars)
            {
                Console.WriteLine($"{bar.Name}");
            }
        }
        catch(Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

CodePudding user response:

In the main, the HTTP response is deserialized to the type List<Fields>. But the JSON rather corresponds the type Root. Try :

//List<Fields> myBars = JsonConvert.DeserializeObject<List<Fields>>(jsonResponse);
Root myBars = JsonConvert.DeserializeObject<Root>(jsonResponse);

CodePudding user response:

Please organise your model well.

Fields myBars = JsonConvert.DeserializeObject<Fields>(jsonResponse);
or
Root myBars = JsonConvert.DeserializeObject<Root>(jsonResponse);



 public class Root
 {
    [JsonProperty("records")]
    public List<Record> Records { get; set; }
 }
  

  public class Record
  {
     [JsonProperty("datasetid")]
     public string Datasetid { get; set; }

     [JsonProperty("recordid")]
     public string Recordid { get; set; }

     [JsonProperty("fields")]
     public Fields Fields { get; set; }

     [JsonProperty("geometry")]
     public Geometry Geometry { get; set; }
  }


public class Fields
 {
   [JsonProperty("other_tags")]
   public string OtherTags { get; set; }

   [JsonProperty("name")]
   public string Name { get; set; }

   [JsonProperty("geo_point_2d")]
   public List<double> GeoPoint2d { get; set; }

   [JsonProperty("phone")]
   public string Phone { get; set; }
 }


public class Geometry
{
  [JsonProperty("type")]
  public string Type { get; set; }

  [JsonProperty("coordinates")]
  public List<double> Coordinates { get; set; }
}

CodePudding user response:

fix your class Root and add a missed Parameters class

      Root data =JsonConvert.DeserializeObject<Root>(jsonResponse);

      List<Fields> myBars = data.Records.Select(f=> f.Fields).ToList();

    foreach (var bar in myBars)
    {
        Console.WriteLine($"{bar.Name}");
    }

public partial class Root
{
    [JsonProperty("nhits")]
    public long Nhits { get; set; }

    [JsonProperty("parameters")]
    public Parameters Parameters { get; set; }

    [JsonProperty("records")]
    public List<Record> Records { get; set; }
}

public partial class Parameters
{
    [JsonProperty("dataset")]
    public List<string> Dataset { get; set; }

    [JsonProperty("rows")]
    public long Rows { get; set; }

    [JsonProperty("start")]
    public long Start { get; set; }

    [JsonProperty("format")]
    public string Format { get; set; }

    [JsonProperty("timezone")]
    public string Timezone { get; set; }
}
  • Related