在 JsonDeserializer 中正确跳过父级

Posted

技术标签:

【中文标题】在 JsonDeserializer 中正确跳过父级【英文标题】:Skipping parent properly in JsonDeserializer 【发布时间】:2021-04-15 22:59:37 【问题描述】:

我收到如下所示的 HttpResponseMessage(数据已编辑):


  "tracks" : 
    "href" : "href_here",
    "items" : [ 
      "album" : 
        //stuff here
      ,
      "name": "name here"
    ,
    
      "album" : 
        //more stuff here
      ,
      "name": "other name here"
    
  

我的模型如下所示:

using System.Text.Json.Serialization;

namespace ProjectName.Models

    public class Track
    
        [JsonPropertyName("album")]
        public Album Album  get; set; 
        
        [JsonPropertyName("name")]
        public string Name  get; set; 
    

然后我尝试像这样反序列化响应:

var response = await _httpClient.GetAsync("URL HERE");

response.EnsureSuccessStatusCode();

return JsonSerializer.Deserialize<IEnumerable<Track>>(await response.Content.ReadAsStringAsync());

我想检索一个曲目列表(对应于 JSON 中的items)。

我找不到在线“跳过”父属性并仅反序列化特定子属性的方法(在本例中为 items)。我不需要href(以及我已删除的其他属性)。

有没有办法做到这一点?

【问题讨论】:

您使用的是 .Net Core 3.x 还是 .Net 5? 老实说,在 .Net 3.1 中,为根和跟踪对象创建包装 DTO 将是最简单的。第二个最简单的方法是加载到JsonDocument 并查询它——但JsonDocument 不支持JSONPath,所以需要做一些工作。大部分工作是编写代码以手动通过 JSON 令牌流式传输,直到您使用 Utf8JsonReader 获得所需的内容。更多的麻烦是值得的。 为什么不创建一个代表根对象的类?那将是最一致的方式。您可以省略不需要的属性。 我不太确定@dbc 的含义,但是编写自定义反序列化器或脆弱的 XPath 将导致更多的工作,而不仅仅是生成与输入 JSON 对应的类并让您的代码读取 @ 987654332@。无论如何,解析器都必须读取 JSON。另见***.com/questions/34222588/… @Jessica - 在 .NET 5 中,您可以反序列化为匿名类型,如 Deserialize anonymous type with System.Text.Json 所示。所以你可以做(await JsonSerializerExtensions.DeserializeAnonymousTypeAsync(await response.Content.ReadAsStreamAsync(), new tracks = new items = default(IEnumerable&lt;Track&gt;) ))?.tracks?.items; 【参考方案1】:
using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace ***

    public class Album
    
    

    public class Item
    
        [JsonPropertyName("album")]
        public Album Album  get; set; 
        [JsonPropertyName("name")]
        public string Name  get; set; 
    

    public class Tracks
    
        [JsonPropertyName("href")]
        public string Href  get; set; 
        [JsonPropertyName("items")]
        public List<Item> Items  get; set; 
    

    public class Root
    
        [JsonPropertyName("tracks")]
        public Tracks Tracks  get; set; 
    

    class Program
    
        static void Main(string[] args)
        
            var jsonStr = "\"tracks\":\"href\":\"href_here\", \"items\" : [\"album\" :  , \"name\": \"name here\"]";

            var root = JsonSerializer.Deserialize<Root>(jsonStr);

           //Here is your "IEnumerable<Track>"
            var items = root.Tracks.Items;
        
    

您的模型必须具有这样的结构,然后它会按预期反序列化您的数据。然后,您可以使用 Linq 将结果转换为您想要的每种格式。

【讨论】:

以上是关于在 JsonDeserializer 中正确跳过父级的主要内容,如果未能解决你的问题,请参考以下文章

Maven - 跳过父项目构建

一般继承 /虚方法 跳过父类执行 祖父类的方法

Spring Data Rest:自定义 JsonDeserializer 中的 @Autowire

在 Kotlin 中使用自定义 JsonDeserializer 进行改造

Springboot通过Converter和JsonDeserializer自定义web入参

java.lang.NoClassDefFoundError: com/fasterxml/jackson/databind/JsonDeserializer