为何JsonConverter<int>需检查TokenType,而JsonConverter<double>无需此操作?
问题原因分析
这是因为System.Text.Json启用AllowReadingFromString后,对整数类型和浮点类型的字符串数值处理逻辑存在差异:
- 对于
double(及其他浮点类型如decimal):启用该选项后,JSON中的字符串数值不会被内置逻辑预解析,Utf8JsonReader会保留原始的String类型Token,所以直接调用reader.GetString()能正常获取到字符串内容,不会报错。 - 对于
int(及其他整数类型如long、short):启用该选项后,内置逻辑会自动将JSON中的字符串数值预解析为Number类型Token,此时reader.TokenType已经是Number而非String,直接调用reader.GetString()就会因为当前Token类型不匹配抛出System.InvalidOperationException。
这种差异的本质是:整数类型的字符串转数值规则更简单统一,内置预解析可以减少后续转换的重复操作;而浮点类型的字符串格式更复杂(比如科学计数法、多语言小数点格式等),保留原始字符串让自定义转换器自行处理更灵活。
解决方案
针对整数类型的自定义转换器,必须先判断当前Token的类型,再选择对应的读取方式:
public class MeasurementsConverter : JsonConverter<int> { public override int Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { return reader.TokenType switch { JsonTokenType.String => int.Parse(reader.GetString()!), JsonTokenType.Number => reader.GetInt32(), _ => throw new JsonException("无效的整数格式") }; } public override void Write(Utf8JsonWriter writer, int value, JsonSerializerOptions options) { writer.WriteNumberValue(value); } }
或者也可以用reader.GetRawText()直接获取当前Token的原始字符串内容,再统一解析:
public override int Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { return int.Parse(reader.GetRawText()); }
内容的提问来源于stack exchange,提问作者Alexandre Bell
相关产品推荐
相关产品推荐

