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

.NET中DateOnly序列化报错:无法将StartObject令牌转为字符串

解决DateOnlyJsonConverter中的"Cannot get the value of a token type 'StartObject' as a string."错误

问题分析

错误的核心原因是当前自定义转换器仅支持读取字符串格式的日期,但实际请求中DateOnly被序列化为了JSON对象(而非字符串)。当JsonReader遇到StartObject类型的Token时,直接调用reader.GetString()会抛出异常——该方法仅适用于String类型的Token。

修复方案

修改DateOnlyJsonConverter的Read方法,同时兼容字符串格式和JSON对象格式的DateOnly输入:

public class DateOnlyJsonConverter : JsonConverter<DateOnly>
{
    private const string Format = "yyyy-MM-dd";

    public override DateOnly Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        // 处理JSON对象格式的DateOnly(如{"Year":2024,"Month":5,"Day":20})
        if (reader.TokenType == JsonTokenType.StartObject)
        {
            int year = 0, month = 0, day = 0;
            while (reader.Read())
            {
                if (reader.TokenType == JsonTokenType.EndObject)
                    break;
                
                if (reader.TokenType == JsonTokenType.PropertyName)
                {
                    var propName = reader.GetString();
                    reader.Read();
                    switch (propName)
                    {
                        case nameof(DateOnly.Year):
                            year = reader.GetInt32();
                            break;
                        case nameof(DateOnly.Month):
                            month = reader.GetInt32();
                            break;
                        case nameof(DateOnly.Day):
                            day = reader.GetInt32();
                            break;
                    }
                }
            }
            return new DateOnly(year, month, day);
        }
        // 处理字符串格式的DateOnly(如"2024-05-20")
        else if (reader.TokenType == JsonTokenType.String)
        {
            var dateStr = reader.GetString();
            if (DateOnly.TryParseExact(dateStr, Format, CultureInfo.InvariantCulture, out DateOnly date))
            {
                return date;
            }
            throw new JsonException($"无法将字符串'{dateStr}'转换为DateOnly类型,格式需为{Format}");
        }
        throw new JsonException($"不支持的Token类型:{reader.TokenType}");
    }

    public override void Write(Utf8JsonWriter writer, DateOnly value, JsonSerializerOptions options)
    {
        writer.WriteStringValue(value.ToString(Format, CultureInfo.InvariantCulture));
    }
}

额外优化建议

  1. 移除重复特性:你已经在Program.cs中全局注册了转换器,无需再在CelestialObjectEntity和CelestialObjectDto的DiscoveryDate字段上添加[JsonConverter(typeof(DateOnlyJsonConverter))],避免重复处理引发潜在问题。

  2. 规范请求格式:确保前端请求日期符合以下两种格式之一:

    • 字符串格式:"DiscoveryDate": "2024-05-20"
    • 对象格式:"DiscoveryDate": {"Year":2024,"Month":5,"Day":20}
  3. 优化异常反馈:控制器中直接返回NoContent()不利于问题排查,建议返回带错误信息的BadRequest:

    catch (Exception ex)
    {
        return BadRequest(new { Message = "添加天体失败", Error = ex.Message });
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 02:46:18