如何使用System.Text.Json将子JSON属性反序列化到父模型属性?
问题描述
- 现有外部生成、无法修改格式的JSON结构,包含章节列表,每个章节的标题嵌套在
tags.title路径下 - 希望移除冗余的嵌套模型类,仅保留单类
Chapter完成反序列化,不需要支持序列化回JSON - 运行环境为VS2022 Preview下的.NET MAUI,使用System.Text.Json作为序列化库
示例源JSON结构:
{ "chapters": [ { "id": 0, "tags": { "title": "Chapter 1" } }, { "id": 1, "tags": { "title": "Chapter 2" } } ] }
目标扁平化模型结构:
public class Chapter { [JsonPropertyName("id")] public int Id { get; set; } public string Title {get; set;} }
实现方法
通过自定义JsonConverter<Chapter>实现嵌套属性的直接读取,不需要保留嵌套类,步骤如下:
- 编写自定义章节转换器,仅实现反序列化逻辑(序列化逻辑因无需求可直接抛出不支持异常)
using System.Text.Json; using System.Text.Json.Serialization; public class ChapterJsonConverter : JsonConverter<Chapter> { public override void Write(Utf8JsonWriter writer, Chapter value, JsonSerializerOptions options) { throw new NotSupportedException("不需要实现序列化逻辑"); } public override Chapter Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { using JsonDocument doc = JsonDocument.ParseValue(ref reader); JsonElement root = doc.RootElement; return new Chapter { Id = root.GetProperty("id").GetInt32(), Title = root.GetProperty("tags").GetProperty("title").GetString() ?? string.Empty }; } }
- 关联转换器和模型,二选一即可:
- 方式一:给模型类加转换器特性
[JsonConverter(typeof(ChapterJsonConverter))] public class Chapter { [JsonPropertyName("id")] public int Id { get; set; } public string Title { get; set; } = string.Empty; }
- 方式二:反序列化时传入配置项,不需要修改模型定义
var jsonOptions = new JsonSerializerOptions { Converters = { new ChapterJsonConverter() } }; // 原有反序列化代码修改为传入options即可 List<Chapter> chapters = JsonSerializer.Deserialize<List<Chapter>>(jsonChapters, jsonOptions) ?? new();
容错优化:如果源JSON可能存在字段缺失的情况,可以改用
TryGetProperty读取属性,避免属性不存在时抛出异常:
public override Chapter Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { using JsonDocument doc = JsonDocument.ParseValue(ref reader); JsonElement root = doc.RootElement; Chapter result = new Chapter(); if (root.TryGetProperty("id", out JsonElement idEle)) { result.Id = idEle.GetInt32(); } if (root.TryGetProperty("tags", out JsonElement tagsEle) && tagsEle.TryGetProperty("title", out JsonElement titleEle)) { result.Title = titleEle.GetString() ?? string.Empty; } return result; }
该实现基于System.Text.Json原生能力,无第三方依赖,完全兼容.NET MAUI的运行时版本,反序列化后直接得到扁平化的Chapter对象,不需要保留冗余的Tags属性和ChapterTags类。
内容的提问来源于stack exchange,提问作者master_ruko
相关产品推荐
相关产品推荐

