First of all, I'm a hobby coder so the longer and more detailed your answer, the faster I will understand. Thanks in advance for your patience.
The project I'm working on is building a client-side class to talk with the REST API of BitMEX (https://testnet.bitmex.com/api/explorer/#/Order).
I tried to generate the c# code from the swagger specifications found on the BitMEX website but I was not successful in getting it to work, even after getting out some bugs. Unfortunately I don't find a lot of documentation about the code that it generates, but that's another discussion. :)
I'm having a situation here where one class should deserialize a JSON call that can have 3 kind of results. I could either have an array of OrderResponse, a single OrderResponse or an OrderError. What is the best way to handle this situation and what is the best place to do all the conversions?
The class for Orders that I have so far, looks like this:
namespace BitMEX.JSONClass.Order
{
public partial class OrderError
{
[JsonProperty("error")]
public Error Error { get; set; }
}
public partial class Error
{
[JsonProperty("message", NullValueHandling = NullValueHandling.Ignore)]
public string Message { get; set; }
[JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)]
public string Name { get; set; }
}
public partial class OrderResponse
{
[JsonProperty("orderID", NullValueHandling = NullValueHandling.Ignore)]
public Guid? OrderId { get; set; }
[JsonProperty("clOrdID")]
public string ClOrdId { get; set; }
... [code omitted for readability...]
}
public partial class OrderError
{
public static OrderError FromJson(string json)
{
return JsonConvert.DeserializeObject<OrderError>(json, BitMEX.JSONClass.Order.Converter.Settings);
}
}
public partial class OrderResponse
{
public static OrderResponse FromJson(string json)
{
return JsonConvert.DeserializeObject<OrderResponse>(json, BitMEX.JSONClass.Order.Converter.Settings);
}
}
public partial class OrdersResponse
{
public static List<OrderResponse> FromJson(string json)
{
return JsonConvert.DeserializeObject<List<OrderResponse>>(json, BitMEX.JSONClass.Order.Converter.Settings);
}
}
internal static class Converter
{
public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
{
MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
DateParseHandling = DateParseHandling.None,
Converters =
{
new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }
},
};
}
}
The method I use to handle this situation looks like this, and I don't really like it because I'm sure it could be cleaner:
private object ProcessJSONOrderResponse(string res, Boolean isArray = false)
{
if (isArray)
{
List<OrderResponse> multiOrderResp = OrdersResponse.FromJson(res);
if (multiOrderResp.Count > 0)
{
return multiOrderResp;
}
else
{
var orderError = OrderError.FromJson(res);
if (orderError.Error != null)
{
return orderError;
}
else
{
orderError = new OrderError();
orderError.Error.Name = "Custom error";
orderError.Error.Message = "No JSON response received...";
return orderError;
}
}
}
else
{
var oderResp = OrderResponse.FromJson(res);
if (oderResp.OrderId != null)
{
return oderResp;
}
else
{
var orderError = OrderError.FromJson(res);
if (orderError.Error != null)
{
return orderError;
}
else
{
orderError = new OrderError();
orderError.Error.Name = "Custom error";
orderError.Error.Message = "No JSON response received...";
return orderError;
}
}
}
}
So what I need is a way of handling JSON deserialization to either OrderResponse, an Array of OrderResponse or OrderError in the most efficient way possible with full error handling. Once I know how to do this I will be able to handle many more cases like this and build my API-client.
Many thanks in advance for shedding some light. I will be forever grateful.