Reputation: 83
I'm currently working on a .NET client for the Zoho Books API in order to integrate some data within my organization. I have been struggling with deserializing the json returned by the API. The problem has been because of inheritance and varying property names. I think I'm looking at creating a custom converter in order to avoid creating response types for every model for the sake of a few varying fields.
I was able to create a custom converter that works for parent responses which look like this:
{
"code" : 0,
"message" : "success",
"invoice" : { // This field varies by model
"invoice_id" : "..."
}
}
I have created a gist for this custom converter.
One of the issues with the custom converter is that when I pass the generic return type down from the web client, I need it in either in the base response format or the paginated response format, and generics are failing me here. My converter doesn't work for paginated responses.
I defined my base type of ZohoBooks Response as so:
namespace ZohoBooks4Net.Responses
{
public class ZohoBooksResponse<T> : IZohoBooksResponse<T>
{
/// <summary>
/// Zoho Books error code. This will be zero for a success response and non-zero in case of an error.
/// </summary>
[JsonProperty("code")]
public int Code { get; set; }
/// <summary>
/// Message for the invoked API.
/// </summary>
[JsonProperty("message")]
public string Message { get; set; }
/// <summary>
/// Comprises the invoked API’s Data.
/// </summary>
public T Resource { get; set; }
}
}
Resource is what I'm calling the third field in the response.
However, when the response returns as paginated, it adds another field.
{
"code": 0,
"message": "success",
"contacts": [
{ "..." }
],
"page_context": {
"page": 1,
"per_page": 200,
"has_more_page": false,
"applied_filter": "Status.All",
"sort_column": "contact_name",
"sort_order": "D"
}
}
So I created this object that describes it:
namespace ZohoBooks4Net.Responses.PaginatedResponses
{
public class PaginatedResponse<T> : ZohoBooksResponse<T>, IPaginatedResponse<T>
{
[JsonProperty("page_context")]
public PageContext Context { get; set; }
}
public class PageContext
{
[JsonProperty("page")]
public int Page { get; set; }
[JsonProperty("per_page")]
public int PerPage { get; set; }
[JsonProperty("has_more_page")]
public bool HasMorePage { get; set; }
}
}
If anyone has any solutions I would really appreciate it.
Upvotes: 2
Views: 470
Reputation: 83
Taking a referenced post from a commenter, I implemented the ReadJson method created by poster of the article. This solved my issue. Here's a link to DynamicPropertyNameConverter on Github Gist.
Upvotes: 0
Reputation: 1083
Books already hosted .Net library in github. In Subscription java client, page context and resources handled separately.
Upvotes: 1
Reputation: 78
Have you tried using the json2csharp web application tool? It will create the classes needed from your JSON response and a root object which can be used with the Newtonsoft JsonCovnert's DeserializeObject method.
Upvotes: 0