能否用Set方法替代JsonProperty处理API返回浮点转整数反序列化问题?
解决方案
方案1:使用自定义JsonConverter(最推荐)
这个方案从根源解决类型不匹配的问题,完全不需要额外定义中转属性,不会触发代码检查告警,可复用性也更高。
针对Newtonsoft.Json的实现
public class ForceIntFromFloatConverter : JsonConverter<int> { public override int ReadJson(JsonReader reader, Type objectType, int existingValue, bool hasExistingValue, JsonSerializer serializer) { var value = Convert.ToDouble(reader.Value); // 校验是否为整数,避免6.1这类非整数值被强转 if (Math.Abs(value - Math.Round(value)) > 1e-6) { throw new ArgumentException($"Tried to parse number {value} to int that is not an int."); } return (int)Math.Round(value); } public override void WriteJson(JsonWriter writer, int value, JsonSerializer serializer) { // 序列化时如果需要输出为float格式可修改此处,默认输出int即可 writer.WriteValue(value); } }
直接在业务属性上标注即可,无需其他中转属性:
[JsonProperty("Quantity")] [JsonConverter(typeof(ForceIntFromFloatConverter))] public int Quantity { get; set; }
针对System.Text.Json的实现
如果你使用.NET自带的System.Text.Json做序列化,转换器实现如下:
public class ForceIntFromFloatConverter : JsonConverter<int> { public override int Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { var value = reader.GetDouble(); if (Math.Abs(value - Math.Round(value)) > 1e-6) { throw new ArgumentException($"Tried to parse number {value} to int that is not an int."); } return (int)Math.Round(value); } public override void Write(Utf8JsonWriter writer, int value, JsonSerializerOptions options) { writer.WriteNumberValue(value); } }
属性标注改为:
[JsonPropertyName("Quantity")] [JsonConverter(typeof(ForceIntFromFloatConverter))] public int Quantity { get; set; }
方案2:最小改动兼容原有实现
如果你不想调整现有逻辑,只需要给私有中转属性加一个无意义的getter即可消除代码检查告警,私有属性不会对外暴露,不影响正常使用。同时注意你原有IsInt方法存在逻辑漏洞,无法正确处理负数场景,建议同步修改:
[JsonProperty("Quantity")] private float QuantityFloat { get => 0; // 加空getter消除告警,反序列化过程不会调用该getter set { if (!IsInt(value)) { throw new ArgumentException("Tried to parse number to Quantity that is not an int."); } Quantity = (int)value; } } public int Quantity { get; set; } // 修复后整数校验逻辑 private static bool IsInt(float value) { return Math.Abs(value - Math.Round(value)) < 1e-6; }
内容的提问来源于stack exchange,提问作者lumpigerAffe
相关产品推荐
相关产品推荐

