在 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<Track>) ))?.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 中正确跳过父级的主要内容,如果未能解决你的问题,请参考以下文章
Spring Data Rest:自定义 JsonDeserializer 中的 @Autowire
在 Kotlin 中使用自定义 JsonDeserializer 进行改造
Springboot通过Converter和JsonDeserializer自定义web入参
java.lang.NoClassDefFoundError: com/fasterxml/jackson/databind/JsonDeserializer