Goga Gate
Goga Gate

Reputation: 47

How to write generic JSON deserializer method?

I'm trying to write a generic method which will deserialize JSON responses. In the end, I am getting an error:

Newtonsoft.Json.JsonSerializationException: 'Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.IEnumerable`1[ClientAddressWFA.Models.Address]' 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.

Here is the code of the method below 👇

public static async Task<IEnumerable<T>> JsonDeserialize<T>(string uri)
    {
        HttpClient client = new HttpClient();
        HttpResponseMessage response = await client.GetAsync(uri);

        var content = await response.Content.ReadAsStreamAsync();

        StreamReader reader = new StreamReader(content);
        JsonReader jReader = new JsonTextReader(reader);

        JsonSerializer jSer = new JsonSerializer();

        return jSer.Deserialize<IEnumerable<T>>(jReader);
    }

This is the schema of the API response: enter image description here

And this is the model. I'm using IEnumerable collection of type Address model to store desirialized data:

public class Address
{

    [JsonProperty("id")]
    public int Id;

    [JsonProperty("streetAddress")]
    public int StreetAddress;

    [JsonProperty("streetName")]
    public string StreetName;

    [JsonProperty("buildingNumber")]
    public int BuildingNumber;

    [JsonProperty("additionalBuildingNumber")]
    public string AdditionalBuildingNumber;

    [JsonProperty("fullAddress")]
    public string FullAddress;

    [JsonProperty("zipCode")]
    public int ZipCode;

    [JsonProperty("coordinateX")]
    public double CoordinateX;

    [JsonProperty("coordinateY")]
    public double CoordinateY;

    [JsonProperty("sozraum")]
    public int Sozraum;

    [JsonProperty("sozialraum")]
    public int Sozialraum;

    [JsonProperty("lebraum")]
    public int Lebraum;

    [JsonProperty("lebensraum")]
    public int Lebensraum;

    [JsonProperty("stimmbezirk")]
    public int Stimmbezirk;

    [JsonProperty("hnr_nur_fb62")]
    public string HnrNurFb62;

    [JsonProperty("gerade")]
    public string Gerade;

    [JsonProperty("district")]
    public string District;

    [JsonProperty("districtNumber")]
    public string DistrictNumber;

    [JsonProperty("wkb_geometry")]
    public string WkbGeometry;

    [JsonProperty("isMain")]
    public bool IsMain;
}

Upvotes: 0

Views: 167

Answers (1)

emagers
emagers

Reputation: 911

The JSON response you're getting has the addresses array nested within a higher-level object. The simplest solution would be to create that high-level response object:

public class Response<T> {
    public List<T> Data {get; set;}
    public bool Success {get;set;}
    public string Message {get;set;}
}

You can then deserialize the Response object in your method and return just the data property from it:

public static async Task<IEnumerable<T>> JsonDeserialize<T>(string uri) {
     //...all the code up until deserialization
     return jSer.Deserialize<Response<T>>(jReader).Data;
}

Upvotes: 3

Related Questions