使用JsonConverter序列化含NaN的double时遇ArgumentException问题求助
解决方案:自定义JsonConverter中高效处理NaN/Infinity序列化
问题根源
全局配置的JsonNumberHandling.AllowNamedFloatingPointLiterals仅对System.Text.Json的默认序列化逻辑生效。当你在自定义JsonConverter中直接调用Utf8JsonWriter.WriteNumberValue时,该方法会严格遵循JSON规范,直接拒绝NaN、正负无穷这类非标准数值,完全忽略全局配置。
高效实现方案
在自定义转换器的Write方法中,提前判断double值的类型,针对NaN/正负无穷直接写入对应的命名浮点字面量,避免字符串转换的额外开销。使用Utf8JsonWriter.WriteRawValue直接写入原生JSON字面量,性能远优于先转字符串再序列化的方式。
修改后的转换器代码:
public class SubConvertor : JsonConverter<Subclass> { public override Subclass Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { return new Subclass(); } public override void Write(Utf8JsonWriter writer, Subclass value, JsonSerializerOptions options) { writer.WriteStringValue("NaaaN"); double num = value.NaN; if (double.IsNaN(num)) { writer.WriteRawValue("NaN"); } else if (double.IsPositiveInfinity(num)) { writer.WriteRawValue("Infinity"); } else if (double.IsNegativeInfinity(num)) { writer.WriteRawValue("-Infinity"); } else { writer.WriteNumberValue(num); } } }
可选:联动全局配置
如果需要和全局的JsonNumberHandling配置保持一致,可以增加判断逻辑,仅当配置允许时才写入命名浮点字面量:
public override void Write(Utf8JsonWriter writer, Subclass value, JsonSerializerOptions options) { writer.WriteStringValue("NaaaN"); double num = value.NaN; bool allowNamedLiterals = (options.NumberHandling & JsonNumberHandling.AllowNamedFloatingPointLiterals) != 0; if (allowNamedLiterals) { if (double.IsNaN(num)) { writer.WriteRawValue("NaN"); return; } else if (double.IsPositiveInfinity(num)) { writer.WriteRawValue("Infinity"); return; } else if (double.IsNegativeInfinity(num)) { writer.WriteRawValue("-Infinity"); return; } } // 不允许则使用默认方法(会抛出异常,或根据需求自定义降级处理) writer.WriteNumberValue(num); }
内容的提问来源于stack exchange,提问作者Liviu Sosu
相关产品推荐
相关产品推荐

