JsonSerializer反序列化泛型类后如何直接获取T对象?
问题描述
现有一段JSON结构如下:
{ "RESPONSE": { "MASDAT": [], "TEXTS": [ { "COMPANY": "", "PLANT": "0001", "PLANTX": "Werk 0001" } ] } }
使用泛型类FMPResponseDto<T>进行反序列化:
public class FMPResponseDto<T> { [JsonPropertyName("RESPONSE")] public required T Response { get; set; } }
反序列化代码示例:
var data = JsonSerializer.Deserialize<FMPResponseDto<T>>(responseBody); return data;
现在需要在反序列化后直接获取内部的T对象(例如FMPFactoryResultDTO),无需手动复制属性——因为大量业务方法仅接收T类型实例。FMPFactoryResultDTO定义如下:
public class FMPFactoryResultDTO { [JsonPropertyName("TEXTS")] public required FMPFactoryItemDto[] Factories { get; init; } [JsonPropertyName("STATUS")] public int Status { get; init; } [JsonPropertyName("MESSAGE")] public string? Message { get; init; } }
解决方案
无需手动复制属性,以下是几种简洁的实现方式:
1. 直接返回反序列化后的Response属性
这是最直接的方案,反序列化完成后直接取出外层包装类的Response属性返回:
var wrapper = JsonSerializer.Deserialize<FMPResponseDto<FMPFactoryResultDTO>>(responseBody); return wrapper.Response;
如果需要复用逻辑,可以封装成通用工具方法:
public static T DeserializeToResponse<T>(string responseBody) { var wrapper = JsonSerializer.Deserialize<FMPResponseDto<T>>(responseBody) ?? throw new InvalidOperationException("反序列化结果为空"); return wrapper.Response; }
调用时只需传入目标类型:
var result = DeserializeToResponse<FMPFactoryResultDTO>(responseBody);
2. 自定义JSON转换器跳过外层包装
如果不想依赖FMPResponseDto<T>的结构,可以自定义JSON转换器,直接将RESPONSE节点的内容反序列化为目标类型:
public class SkipWrapperConverter<T> : JsonConverter<T> { public override T? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { if (reader.TokenType != JsonTokenType.StartObject) throw new JsonException("无效的JSON格式"); while (reader.Read()) { if (reader.TokenType == JsonTokenType.PropertyName && reader.GetString() == "RESPONSE") { reader.Read(); // 进入RESPONSE节点内部 return JsonSerializer.Deserialize<T>(ref reader, options); } reader.Skip(); // 跳过其他无关属性 } throw new JsonException("未找到RESPONSE节点"); } public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options) { // 如需序列化回原格式,可在此添加外层包装逻辑 writer.WriteStartObject(); writer.WritePropertyName("RESPONSE"); JsonSerializer.Serialize(writer, value, options); writer.WriteEndObject(); } }
使用时在序列化选项中添加转换器:
var options = new JsonSerializerOptions(); options.Converters.Add(new SkipWrapperConverter<FMPFactoryResultDTO>()); var result = JsonSerializer.Deserialize<FMPFactoryResultDTO>(responseBody, options);
3. 利用JSON路径直接提取节点(适用于Newtonsoft.Json)
如果项目使用Newtonsoft.Json(Json.NET),可以直接通过JSON路径提取RESPONSE节点内容再反序列化,无需定义外层包装类:
var jObject = JObject.Parse(responseBody); var responseToken = jObject.SelectToken("$.RESPONSE"); var result = responseToken.ToObject<FMPFactoryResultDTO>();
内容的提问来源于stack exchange,提问作者user6408649
相关产品推荐
相关产品推荐

