2

QuickBooks Online uses for their API the following response:

{
  "QueryResponse": {
    "Customer": [
      {
        "GivenName": "Test"
      },
      {
        "GivenName": "Test 2"
      }
    ],
    "startPosition": 1,
    "maxResults": 2
  },
  "time": "2018-08-11T16:12:10.808-07:00"
}

I'm trying to create a C# model from this:

public class QueryResponseRoot<T> where T : IQuickbooksBaseEntity
{
    [JsonProperty("QueryResponse")]
    public QueryResponse<T> QueryResponse { get; set; }

    [JsonProperty("time", Required = Required.Always)]
    public DateTimeOffset Time { get; set; }
}

public class QueryResponse<T> where T : IQuickbooksBaseEntity
{
    [JsonProperty, JsonConverter(typeof(QuickbooksResponseConverter))]
    public IList<T> Results { get; set; }

    [JsonProperty("startPosition")]
    public Int64 StartPositions { get; set; }

    [JsonProperty("maxResults")]
    public Int64 MaxResults { get; set; }
}

The API has multiple entities which are all defined with the IQuickbooksBaseEntity interface.

The problem is that if you get Customers it will return Customer as a property on the QueryResponse object, but if you get something else like Accounts the response looks like this:

{
  "QueryResponse": {
    "Account": [
      {
        "Name": "Accounts Payable (A/P)"
      }
    ],
    "startPosition": 1,
    "maxResults": 90
  },
  "time": "2018-08-11T16:14:55.309-07:00"
}

How can I map the property Customer or Account or any other one from a known list to the Results property in my model?

Import to know (probably) is that I do know when I call the API which property will be returned to me (i.e. Customer or Account).

Now I'm solving it directly in code, but I'm not sure if casting it dynamic has large performance issues:

var resultObjectJson = JsonConvert.DeserializeObject<dynamic>(body);

var entityName = typeof(T).Name;

var maxResults = (Int64) resultObjectJson.QueryResponse.maxResults;
var startPositions = (Int64) resultObjectJson.QueryResponse.startPosition;
var results = ((JArray) resultObjectJson.QueryResponse[entityName]).ToObject<List<T>>();

var resultRoot = new QueryResponseRoot<T>
{
    QueryResponse = new QueryResponse<T>
    {
        MaxResults = maxResults,
        StartPositions = startPositions,
        Results = results
    }
};

return resultRoot.QueryResponse;
Roger Far
  • 2,178
  • 3
  • 36
  • 67
  • Looks like a duplicate of [Json.NET getting generic property types name on serialization?](https://stackoverflow.com/q/26629430/3744182) and/or [How to get the name of `` from generic type and pass it into JsonProperty()?](https://stackoverflow.com/q/39128650/3744182). Agree? – dbc Aug 12 '18 at 01:24
  • @dbc I'm not 100% positive but it looks like they are trying to do serializing, I need to be able to deserialize. – Roger Far Aug 12 '18 at 02:02
  • Both answers use a [custom contract resolver](https://www.newtonsoft.com/json/help/html/contractresolver.htm#CustomIContractResolverExamples) and so should work for both serialization and deserialization. – dbc Aug 12 '18 at 03:19
  • Did you give either answer a try? – dbc Aug 12 '18 at 03:28
  • I'm not very familias with custom contracts, but I didn't see how you can re-map multiple properties to one without having an instance of the result yet? – Roger Far Aug 12 '18 at 21:48
  • The contract resolver from [How to get the name of `` from generic type and pass it into JsonProperty()?](https://stackoverflow.com/a/39129145/3744182) works just fine, see https://dotnetfiddle.net/PeWAYp for a demo. You have to add `[JsonPropertyGenericTypeName(0)]` to `public IList Results { get; set; }`. You may want to [cache the contract resolver for best performance](https://stackoverflow.com/a/33558665/3744182). It can work because the contract resolver knows the concrete type being serialized, namely `QueryResponse`. – dbc Aug 13 '18 at 06:41
  • OTOH the one from [Json.NET getting generic property types name on serialization?](https://stackoverflow.com/a/26635837/3744182) does not work, since `Results` has type `IList` rather than `T`, see https://dotnetfiddle.net/DOzVi7 – dbc Aug 13 '18 at 06:43

0 Answers0