You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 11:52:22