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

自定义JsonConverter中JsonSerializer.Deserialize(ref reader)反序列化失败

问题分析与解决方案

问题根源

你的WeatherForecastData是只读结构体,且未为反序列化指定可用的构造函数。System.Text.Json默认要求结构体要么有无参构造函数,要么用[JsonConstructor]特性标记一个与JSON键匹配的带参构造函数。当前代码中,WeatherForecastData的构造函数要么接收string类型的Summary参数(与JSON中的int类型不匹配),要么未被序列化器识别,导致反序列化时只能生成默认值的结构体实例(所有字段为默认值,看起来像“空”)。

解决方案

方案一:标记适配反序列化的构造函数

给WeatherForecastData添加一个与JSON键严格匹配的带参构造函数,并标记[JsonConstructor]特性,让序列化器明确使用该构造函数创建实例:

internal readonly struct WeatherForecastData
{
    public DateTime Date { get; }
    public int TC { get; }
    public int Summary { get; }

    // 用于反序列化的构造函数,参数名与JSON键一一对应
    [JsonConstructor]
    public WeatherForecastData(DateTime Date, int TC, int Summary)
    {
        this.Date = Date;
        this.TC = TC;
        this.Summary = Summary;
    }

    // 保留用于序列化转换的原构造函数
    public WeatherForecastData(DateTime date, int temperatureCelsius, string summary)
    {
        this.Date = date;
        this.TC = temperatureCelsius;
        this.Summary = summary == "Hot" ? 1 : summary == "Cold" ? -1 : 0;
    }
}

方案二:手动读取Utf8JsonReader属性

如果不想修改WeatherForecastData,可以在Read方法中直接手动解析JSON的每个属性,跳过中间结构体的反序列化步骤:

public override WeatherForecast? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
    if (reader.TokenType != JsonTokenType.StartObject)
    {
        throw new JsonException("JSON格式错误,预期对象起始标记");
    }

    DateTime date = default;
    int tempC = default;
    int summaryCode = default;

    while (reader.Read())
    {
        if (reader.TokenType == JsonTokenType.EndObject)
        {
            break;
        }

        if (reader.TokenType != JsonTokenType.PropertyName)
        {
            throw new JsonException("JSON格式错误,预期属性名");
        }

        var propName = reader.GetString()!;
        reader.Read();

        switch (propName)
        {
            case "Date":
                date = reader.GetDateTime();
                break;
            case "TC":
                tempC = reader.GetInt32();
                break;
            case "Summary":
                summaryCode = reader.GetInt32();
                break;
            default:
                reader.Skip(); // 跳过未知属性,避免解析失败
                break;
        }
    }

    return new WeatherForecast
    {
        Date = date,
        TemperatureCelsius = tempC,
        Summary = summaryCode == 1 ? "Hot" : summaryCode == -1 ? "Cold" : string.Empty
    };
}

验证修改

修改后重新运行TestDeserialize测试,即可正常反序列化出WeatherForecast实例。

内容的提问来源于stack exchange,提问作者CaseyHofland

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 19:41:07