philipp-fx
philipp-fx

Reputation: 649

How to deserialize non-array json to child class that implements List<T>?

I have the following class:

public class PagedClientModelList<T> : List<T>
{
    public int TotalCount { get; set; }
    public int PageSize { get; set; }
    public int CurrentPage { get; set; }
    public int TotalPages { get; set; }
}

Two different json strings will be deserialized into an instance of this object:

Deserializing to List<T> is no problem:

var result = JsonConvert.DeserializeObject<PagedClientModelList<Person>>
                 (httpResponseMessage.Content.ReadAsStringAsync().Result);

for json string:

[
  {
    "id": 1,
    "name": "Hans"
  },
  {
    "id": 2,
    "name": "Peter"
  },
  {
    "id": 3,
    "name": "Max"
  }
]

However, when I want to deserialize the header, which is a non-array json, the jsonConverter wants to deserialze again to List<T> and throws an exception, but I need to serialize it to the child class PagedClientModelList<T>:

if (httpResponseMessage.Headers.TryGetValues("X-Pagination", out var xPagination))
{
    result = JsonConvert.DeserializeObject<PagedClientModelList<Person>>(xPagination.First());

    // throws exception: Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type [... because it requires json array]
}

for the corresponding header value:

{
  "totalCount": 12,
  "pageSize": 3,
  "currentPage": 1,
  "totalPages": 4
}

How can I deserialize a non-array json to a child class that implements List<T>?

Upvotes: 3

Views: 330

Answers (2)

Rui Jarimba
Rui Jarimba

Reputation: 18094

Ok, here's an alternative, changing slightly your models:

public class Person
{
    [JsonProperty("id")]
    public int Id { get; set; }

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

public class PagedClientModelList<T> where T : class, new()
{
    [JsonProperty("totalCount")]
    public int TotalCount { get; set; }

    [JsonProperty("pageSize")]
    public int PageSize { get; set; }

    [JsonProperty("currentPage")]
    public int CurrentPage { get; set; }

    [JsonProperty("totalPages")]
    public int TotalPages { get; set; }

    [JsonProperty("content")]
    public List<T> Content { get; set; }

    public PagedClientModelList()
    {
        Content = new List<T>();
    }
}

Testing the code:

class Program
{
    static void Main(string[] args)
    {
        string header = @"{
""totalCount"": 12,
""pageSize"": 3,
""currentPage"": 1,
""totalPages"": 4
}";

        string content = @"[
{
    ""id"": 1,
    ""name"": ""Hans""
},
{
    ""id"": 2,
    ""name"": ""Peter""
},
{
    ""id"": 3,
    ""name"": ""Max""
}
]";

        var modelList = JsonConvert.DeserializeObject<PagedClientModelList<Person>>(header);
        modelList.Content = JsonConvert.DeserializeObject<List<Person>>(content);

        Console.ReadKey();
    }
}

Upvotes: 2

philipp-fx
philipp-fx

Reputation: 649

In order to move forward, I implemented the following workaround:

public class PagedClientModelList<T> : List<T>
{
    public PaginationMetadata PaginationMetadata { get; set; }
}

public class PaginationMetadata
{
    public int TotalCount { get; set; }
    public int PageSize { get; set; }
    public int CurrentPage { get; set; }
    public int TotalPages  { get; set; }
}

Now I am able to deserialize without any problems:

var result = JsonConvert.DeserializeObject<PagedClientModelList<Person>>
                 (httpResponseMessage.Content.ReadAsStringAsync().Result);

if (httpResponseMessage.Headers.TryGetValues("X-Pagination", out var xPagination))
{
    result.PaginationMetadata = JsonConvert.DeserializeObject<PaginationMetadata>(xPagination.First());
}

Upvotes: -1

Related Questions