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

Newtonsoft.Json序列化:JSON数值类型识别错误及单元测试问题

JSON序列化/反序列化适配问题解决方案

1. 可以强制指定字段以浮点数类型导入

有两种可靠的实现方式:

全局配置统一处理

在反序列化时通过JsonSerializerSettings强制将所有数值解析为double,不管JSON中是整数还是小数格式:

var serializerSettings = new JsonSerializerSettings
{
    FloatParseHandling = FloatParseHandling.Double
};
var actualModel = JsonConvert.DeserializeObject<JsonContainer>(expectedJson, serializerSettings);

针对单个字段精准处理

如果只需要特定字段按浮点数解析,给DTO字段添加JsonConverter特性:

public class Tax
{
    [JsonProperty("tax", NullValueHandling = NullValueHandling.Ignore)]
    [JsonConverter(typeof(DoubleConverter))]
    public double? Tax;
}

至于大小写命名问题,你已经通过[JsonProperty("tax")]完成了C# PascalCase与JSON小写字段的映射,这个方案完全可行,无需额外调整。

2. 当前单元测试方法存在缺陷

问题出在反序列化→序列化后的JToken对比逻辑:JSON原始的整数(如65)会被反序列化为double类型,再序列化会变成65.0,导致前后JToken的数值类型(一个是JTokenType.Integer,一个是JTokenType.Float)不一致,触发断言失败。

优化方案:调整断言逻辑

利用FluentAssertions的灵活配置,忽略数值类型差异,只验证值的等价性:

actual.Should().BeEquivalentTo(expected, options =>
    options.Using<JValue>(ctx =>
    {
        if ((ctx.Subject.Type == JTokenType.Float && ctx.Expectation.Type == JTokenType.Integer) ||
            (ctx.Subject.Type == JTokenType.Integer && ctx.Expectation.Type == JTokenType.Float))
        {
            Convert.ToDouble(ctx.Subject).Should().Be(Convert.ToDouble(ctx.Expectation));
        }
        else
        {
            ctx.Subject.Should().Be(ctx.Expectation);
        }
    }).WhenTypeIs<JValue>());

替代思路:直接验证DTO对象

跳过序列化回JSON的步骤,直接从原始JToken中提取预期值,与反序列化后的DTO属性做对比,彻底规避类型表示差异问题:

var expectedTaxValue = (double)expected.SelectToken("$.Tax.tax");
actualModel.Tax.Tax.Should().Be(expectedTaxValue);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 03:10:28