1

I have the following JSON object being returned from an API call beyond my control:

{
  "GetBusinessGroupsRestResult": [
  {
    "BgId": 1,
    "NodeLevel": 1,
    "BusinessDescription": "Business Groups",
    "BusinessName": "Root",
    "nodegroupid": 2,
    "nodegroupname": "Root",
    "nodegroupdesc": "Root",
    "sorkkey": "Root",
    "Marked": 2
  },
  {
    "BgId": 2,
    "NodeLevel": 2,
    "BusinessDescription": "Business A",
    "BusinessName": "Business A",
    "ParentID": 1,
    "nodegroupid": 3,
    "nodegroupname": "Business A",
    "nodegroupdesc": "Business A",
    "sorkkey": "Business A",
    "Marked": 2
  },
  ...
 ]
}

I have created the following class structure in an attempt to deserialise it into C# object instances:

public class GetBusinessGroupsRestResult
{
    public List<BusinessGroup> BusinessGroups { get; set; }
}

public class BusinessGroup
{
    [DeserializeAs(Name = "BgId")]
    public int BusinessGroupId { get; set; }

    public int NodeLevel { get; set; }
    public string BusinessDescription { get; set; }
    public string BusinessName { get; set; }

    [DeserializeAs(Name = "ParentID")]
    public int ParentId { get; set; }

    [DeserializeAs(Name = "nodegroupid")]
    public int NodeGroupId { get; set; }

    [DeserializeAs(Name = "nodegroupname")]
    public string NodeGroupName { get; set; }

    [DeserializeAs(Name = "sorkkey")]
    public string SortKey { get; set; }

    public int Marked { get; set; }
}

I am trying to deserialise it using RestSharp, specifying the RootElement as GetBusinessGroupsRestResult. When attempting the deserialisation using RestSharp's IRestResponse<T> Execute<T>(RestRequest), I recieve the following error:

System.InvalidCastException: Unable to cast object of type 'RestSharp.JsonArray' to type 'System.Collections.Generic.IDictionary`2[System.String,System.Object]'.

I've managed to deserialise responses from this API that don't return lists before, for example:

{
  "AcquireSecurityTokenRestResult": {
    "SecurityToken": "SECURITY-TOKEN",
    "SessionLength": 600000,
    "APIVersion": "VERSION"
  }
}

With the following POCO:

public class AcquireSecurityTokenRestResult
{
    public string SecurityToken { get; set; }
    public int SessionLength { get; set; }
    [DeserializeAs(Name = "APIVersion")]
    public string ApiVersion { get; set; }
}

Can anyone point me in the right direction here? Thank you!

2 Answers 2

2

Managed to make it work. The Execute part:

var client = new RestClient("http://localhost:3000/");
var request = new RestRequest("main", Method.GET);
var response = client.Execute<RootObject>(request);

And the classes:

public class RootObject
{
    public List<BusinessGroup> GetBusinessGroupsRestResult { get; set; }
}

public class BusinessGroup
{
    [DeserializeAs(Name = "BgId")]
    public int BusinessGroupId { get; set; }

    public int NodeLevel { get; set; }
    public string BusinessDescription { get; set; }
    public string BusinessName { get; set; }

    [DeserializeAs(Name = "ParentID")]
    public int ParentId { get; set; }

    [DeserializeAs(Name = "nodegroupid")]
    public int NodeGroupId { get; set; }

    [DeserializeAs(Name = "nodegroupname")]
    public string NodeGroupName { get; set; }

    [DeserializeAs(Name = "nodegroupdesc")]
    public string NodeGroupDesc { get; set; }

    [DeserializeAs(Name = "sorkkey")]
    public string SortKey { get; set; }

    public int Marked { get; set; }
}

Since the main response is an object which contains an array called GetBusinessGroupsRestResult, you need that in your root object as well.

You can basically fix your example by adding a DeserializeAs attribute to the BusinessGroups property in your GetBusinessGroupsRestResult class:

public class GetBusinessGroupsRestResult
{
    [DeserializeAs(Name = "GetBusinessGroupsRestResult")]
    public List<BusinessGroup> BusinessGroups { get; set; }
}
Sign up to request clarification or add additional context in comments.

1 Comment

It makes so much sense when you see the solution! Thank you! I should note that in my implementation I was creating the RestRequest with a wrapper function that set the RootElement property (e.g. here to GetBusinessGroupsRestResult) - for the other API calls like AcquireSecurityTokenRest this was required, but here it would cause deserialisation to fail and I had to set RootElement to null in order for the [DeserializeAs(Name = "GetBusinessGroupsRestResult")] annotation to have the desired effect.
1

More than an answer, piece of advice. Instead of using RESTSharp why don't you use Json.NET?

I ran into issues with RESTSharp that works wonderfully in Json.NET.

4 Comments

I chose to use RestSharp as it allows me to handle the creation and execution of HTTP requests and the deserialisation of the response in one place. For example: var response = client.Execute<RootObject>(request);. It meets my requirements for the moment in a nice, succint manner. What sort of issues did you run into? Thanks.
@AdamJames sorry if I did not explain myself correctly. I use RESTSharp as well to make the call, but once I get the response I use Json.NET to work with the JSON response I received. I kept running into exceptions deserializing the response on seemingly proper JSON that was handled fine by Json.NET which is also more powerful and flexible. So in summary RESTSharp I found it to be my preferred library for making calls and then I used the other one for interpreting the response.
Thank you for clarifying that - I have a Pluralsight subscription so I'll be sure to watch your course and keep your approach in mind.
Hope it helps you. It certainly did for me when I used both libraries together.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.