如何用System.Text.Json反序列化含额外属性的字典式JSON?
解决方案
针对这种混合固定属性(traceId)和动态日期键的JSON结构,以下是两种基于System.Text.Json的可行处理方案:
方案一:用JsonExtensionData定义根类(推荐)
创建包含固定属性和动态数据的根类,通过JsonExtensionData自动收集未显式定义的日期键,再转换为FreeSlots对象:
public class FreeSlotsResponse { [JsonPropertyName("traceId")] public string? TraceId { get; set; } [JsonExtensionData] private Dictionary<string, JsonElement> _dynamicDateData { get; set; } = new(); // 转换并返回日期与FreeSlots的映射 public Dictionary<string, FreeSlots> DateToFreeSlots { get { var result = new Dictionary<string, FreeSlots>(); foreach (var kvp in _dynamicDateData) { var freeSlots = JsonSerializer.Deserialize<FreeSlots>(kvp.Value); result.Add(kvp.Key, freeSlots!); } return result; } } } // 原FreeSlots类保持不变 public class FreeSlots { [JsonConstructor] public FreeSlots(){} [JsonPropertyName("slots")] public List<string>? slots; }
使用方式
直接反序列化为根类,即可同时获取traceId和日期对应的FreeSlots:
string jsonResponse = "你的API响应JSON字符串"; var response = JsonSerializer.Deserialize<FreeSlotsResponse>(jsonResponse); // 访问traceId string? traceId = response?.TraceId; // 访问日期对应的FreeSlots集合 var dateSlots = response?.DateToFreeSlots;
方案二:直接解析JsonDocument(灵活处理)
若不想额外定义根类,可直接解析JsonDocument,手动提取traceId并转换日期键:
string jsonResponse = "你的API响应JSON字符串"; using var doc = JsonDocument.Parse(jsonResponse); var rootElement = doc.RootElement; // 提取traceId string? traceId = rootElement.TryGetProperty("traceId", out var traceIdElement) ? traceIdElement.GetString() : null; // 转换日期键到FreeSlots字典 var dateSlots = new Dictionary<string, FreeSlots>(); foreach (var property in rootElement.EnumerateObject()) { if (property.Name != "traceId") { var freeSlots = property.Value.Deserialize<FreeSlots>(); dateSlots.Add(property.Name, freeSlots!); } }
问题原因说明
你之前直接反序列化为Dictionary<string, JsonElement>时,traceId会被当作字典的一个键而非独立属性,若后续反序列化FreeSlots时未正确匹配JSON结构,就可能导致slots为空。上述两种方案均规避了该问题,同时保留了traceId的提取逻辑。
内容的提问来源于stack exchange,提问作者Ryan Mickey
相关产品推荐
相关产品推荐

