使用 RestSharp Client 反序列化嵌套的 JSON 响应

本文关键字:JSON 响应 嵌套 反序列化 RestSharp Client 使用 | 更新日期: 2023-09-27 18:30:16

我想使用一个 REST API 并反序列化嵌套的 JSON 响应。为此,我尝试创建一些表示 JSON 响应 [1] 的 POCO 类。响应如下所示:

{
  "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"
          (...)

所以我创建了以下 POCO 类:

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; }
}

这是 API 代码:

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);

编辑1:我发现了一个错别字,安富利课程中的Type属性应命名为Types

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

现在返回值如下所示:

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

编辑2:我使用List<CourseType>而不是Jaanus提出的List<CourseTypeContainer>实现了Course.Types属性。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

现在response.Data.Types终于被填满了。但是,响应。Data.Types.Description仍然没有正确填写,因为有一个额外的语言层(例如"EN")。如何在不为每种语言创建 PACO 的情况下解决此问题?

编辑3:我不得不添加一个额外的CourseTypeDescriptionDetails类,在那里我将存储描述性数据。在我的课程类型描述中,我为每种语言添加了类型列表的属性。代码片段:

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; }
}

它现在可以工作了,但我需要为每种语言的 CourseTypeDescription 添加另一个属性。

OLD:返回值为

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

那么为什么我的回答。键入等于 null?我做错了什么?

谢谢

资源:[1] RestSharp 反序列化与 JSON 数组

使用 RestSharp Client 反序列化嵌套的 JSON 响应

尝试将其用作 POCO:

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

现在你有CourseTypeContainer列表。CourseTypeContainer

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

因此,当您尝试获得response.Data.Types[0].AvnetCourseType时,您需要在内部进行现场AvnetCourseType CourseTypeContainer

或者我认为你想要的实际上是这个公共List<CourseType> Types { get; set; },你不需要那里的容器。

以防万一这对其他人有帮助,我在这里尝试了所有内容,但它仍然不适用于当前版本的 RestSharp (106.6.2)。据我所知,RestSharp完全忽略了RootElement属性,即使它是顶级的。我的解决方法是手动告诉它拉取嵌套的 JSON,然后进行转换。我用 JSON.Net 来完成这个。

var response = restClient.Execute<T>(restRequest);
response.Content = JObject.Parse(response.Content)[restRequest.RootElement].ToString();
return new JsonDeserializer().Deserialize<T>(response);

我使用 http://json2csharp.com/从 JSON 创建 C# 类。然后,将 RootObject 重命名为我正在创建的模型文件的类名嵌套 json 中的所有数据都可以在 RestSharp 反序列化后访问,类似于 responseBody.data.Subject.Alias其中数据、主题和别名是收到的响应 JSON 内的嵌套节点。