FluentAssertions比较对象模型时抛出异常,如何解决?
解决JSON类型混合导致的序列化对比异常问题
问题根源
外部数据源返回的JSON里,同一个字段存在类型混合(比如某个字段有时是数字123,有时是字符串"123"),但你的OrderRetrieveResponse模型字段类型是固定的(比如int或string)。反序列化后再序列化时,会统一成模型定义的类型,和原JSON的JToken类型不一致,导致BeEquivalentTo对比失败。
修复方案
1. 用JToken保留原始类型
把存在类型混合的字段改成JToken类型,这样反序列化时会完整保留原始JSON的类型信息,再序列化回JToken后和原数据完全一致,对比就不会报错:
public class OrderRetrieveResponse { // 其他字段不变 public JToken OrderNumber { get; set; } // 替换原来的int/string类型 }
2. 自定义转换器兼容类型转换
如果要保持模型的强类型(比如还是用int),可以写个自定义JSON转换器,自动处理数字和字符串的转换:
public class FlexibleIntConverter : JsonConverter<int> { public override int ReadJson(JsonReader reader, Type objectType, int existingValue, bool hasExistingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.String) { if (int.TryParse(reader.Value.ToString(), out var result)) return result; throw new JsonException("无法将字符串转为整数"); } else if (reader.TokenType == JsonToken.Integer) { return Convert.ToInt32(reader.Value); } throw new JsonException("不支持的字段类型"); } public override void WriteJson(JsonWriter writer, int value, JsonSerializer serializer) { writer.WriteValue(value); } }
然后给模型字段加上转换器标记:
public class OrderRetrieveResponse { // 其他字段不变 [JsonConverter(typeof(FlexibleIntConverter))] public int OrderNumber { get; set; } }
注意:如果原始JSON里的字符串没法转成目标类型,要提前处理转换失败的情况。
3. 修改测试对比规则忽略类型差异
如果不想改业务代码,只需要验证值是否正确,可以在对比时忽略类型差异,只比较字符串形式的值:
actual.Should().BeEquivalentTo(expected, options => options.Using<JToken>(ctx => { ctx.Subject.ToString().Should().Be(ctx.Expectation.ToString()); }).WhenTypeIs<JToken>() );
这种方式适合只关心值一致,不严格要求类型完全匹配的场景。
方案选择
- 要严格保留原始JSON类型:选方案1;
- 要强类型模型且兼容混合输入:选方案2;
- 只验证值正确性,不想动业务代码:选方案3。
内容的提问来源于stack exchange,提问作者Fysicus
相关产品推荐
相关产品推荐

