Search code examples
c#jsonpocorestsharp

Deserialize nested JSON Response with RestSharp Client


I'd like to consume a REST Api and deserialize the nested JSON Response. For that purpose I tried to create some POCO classes which represent the JSON Response [1]. The response looks like this:

{
  "success": true,
  "message": "OK",
  "types": 
  [
    {
      "name": "A5EF3-ASR",
      "title": "ITIL Foundation Plus Cloud Introduction",
      "classroomDeliveryMethod": "Self-paced Virtual Class",
      "descriptions": {
        "EN": {
          "description": "some Text null",
          "overview": null,
          "abstract": "Some other text",
          "prerequisits": null,
          "objective": null,
          "topic": null
        }
      },
      "lastModified": "2014-10-08T08:37:43Z",
      "created": "2014-04-28T11:23:12Z"
    },
    {
      "name": "A4DT3-ASR",
      "title": "ITIL Foundation eLearning Course + Exam",
      "classroomDeliveryMethod": "Self-paced Virtual Class",
      "descriptions": {
        "EN": {
          "description": "some Text"
          (...)

So I created the following POCO classes:

public class Course
{
    public bool success { get; set; }
    public string Message { get; set; }
    public List<CourseTypeContainer> Type { get; set; }
}

/* each Course has n CourseTypes */
public class CourseType
{
    public string Name { get; set; }
    public string Title { get; set; }
    public List<CourseTypeDescriptionContainer> Descriptions { get; set; }
    public DateTime LastModified { get; set; }
    public DateTime Created { get; set; }
}
public class CourseTypeContainer
{
    public CourseType CourseType { get; set; }
}


/* each CourseType has n CourseTypeDescriptions */
public class CourseTypeDescription
{
    public string Description { get; set; }
    public string Overview { get; set; }
    public string Abstract { get; set; }
    public string Prerequisits { get; set; }
    public string Objective { get; set; }
    public string Topic { get; set; }
}
public class CourseTypeDescriptionContainer
{
    public CourseTypeDescription CourseTypeDescription { get; set; }
}

And this is the API Code:

var client = new RestClient("https://www.someurl.com");
client.Authenticator = new HttpBasicAuthenticator("user", "password");

var request = new RestRequest();
request.Resource = "api/v1.0/types";
request.Method = Method.GET;
request.RequestFormat = DataFormat.Json;

var response = client.Execute<Course>(request);

EDIT 1: I found a Typo, the Type property in AvnetCourse should be named Types:

public List<AvnetCourseTypeContainer> Type { get; set; }    // wrong
public List<AvnetCourseTypeContainer> Types { get; set; }   // correct

Now the return values look like:

response.Data.success = true                    // CORRECT
repsonse.Data.Message = "OK"                    // CORRECT
response.Data.Types = (Count: 1234);            // CORRECT
response.Data.Types[0].AvnetCourseType = null;  // NOT CORRECT

EDIT 2: I implemented the Course.Types Property using a List<CourseType> instead of a List<CourseTypeContainer>, as proposed by Jaanus. The same goes for the CourseTypeDescriptionContainer:

public List<CourseTypeContainer> Type { get; set; }                     // OLD
public List<CourseTypeDescriptionContainer> Descriptions { get; set; }  // OLD
public List<CourseType> Type { get; set; }                              // NEW
public List<CourseTypeDescription> Descriptions { get; set; }           // NEW

Now the response.Data.Types finally are properly filled. However, the response.Data.Types.Descriptions are still not properly filled, since there is an additional language layer (e.g. "EN"). How can I solve this, without creating a PACO for each language?

EDIT 3: I had to add an additional CourseTypeDescriptionDetails class, where I would store the descriptive Data. In my CourseTypeDescription I added a property of the Type List for each language. Code Snippet:

public class AvnetCourseType
{
    public List<CourseTypeDescription> Descriptions { get; set; }
    // other properties
}
public class CourseTypeDescription
{
    public List<CourseTypeDescriptionDetails> EN { get; set; } // English
    public List<CourseTypeDescriptionDetails> NL { get; set; } // Dutch
}
public class CourseTypeDescriptionDetails
{
    public string Description { get; set; }
    public string Overview { get; set; }
    public string Abstract { get; set; }
    public string Prerequisits { get; set; }
    public string Objective { get; set; }
    public string Topic { get; set; }
}

It works now, but I need to add another property to CourseTypeDescription for each language.

OLD: The return values are

response.Data.success = true            // CORRECT
repsonse.Data.Message = "OK"            // CORRECT
response.Data.Type = null;              // WHY?

So why does my response.Type equal null? What am I doing wrong?

Thank you

Resources: [1] RestSharp Deserialization with JSON Array


Solution

  • Try using this as POCO:

    public class Course
    {
        public bool success { get; set; }
        public string message { get; set; }
        public List<CourseTypeContainer> Types { get; set; }
    }
    

    Now you have list of CourseTypeContainer. And CourseTypeContainer is

    public class CourseTypeContainer
    {
        public CourseType CourseType { get; set; }
    }
    

    So when you are trying to get response.Data.Types[0].AvnetCourseType , then you need to have field AvnetCourseType inside CourseTypeContainer

    Or I think what you want is actually this public List<CourseType> Types { get; set; }, you don't need a container there.