C# WebAPI集成Jil序列化器反序列化抛出Expected digit异常求助
解决Jil反序列化时的"Expected digit"错误
这个错误Jil.DeserializationException: 'Expected digit'通常发生在Jil尝试将非数字内容反序列化为数值类型(比如你的long类型的UserId或MobileDeviceId)时。结合你的代码和异常栈,我来帮你排查和解决问题:
可能的原因及对应解决方案
1. 请求JSON中的数值字段格式无效
最常见的情况是你的POST请求里,UserId或MobileDeviceId字段的值不是有效的整数:
- 比如传了字符串(
"UserId": "123"而不是"UserId": 123) - 传了
null(但你的模型里这两个字段是值类型long,不能为null) - 传了空字符串或其他非数字格式
解决方法:
- 检查测试请求的JSON格式,确保这两个字段是纯数字类型,比如:
{ "UserId": 12345, "MobileDeviceId": 67890, "IsInitialLoad": true } - 如果业务上允许这两个字段为null,将模型改成可空类型:
public class ReuestTest { public long? UserId { get; set; } public long? MobileDeviceId { get; set; } public bool IsInitialLoad { get; set; } }
2. JilFormatter的流读取逻辑问题
你的ReadFromStreamAsync方法直接同步读取流,没有考虑异步场景下的流完整性,可能导致读取到不完整的JSON内容,进而引发反序列化错误。
修复后的ReadFromStreamAsync方法:
public override async Task<object> ReadFromStreamAsync(Type type, Stream input, HttpContent content, IFormatterLogger formatterLogger) { using (var reader = new StreamReader(input, SupportedEncodings.First(), true)) { var json = await reader.ReadToEndAsync(); var deserialize = TypedDeserializers.GetTyped(type); using (var stringReader = new StringReader(json)) { var result = deserialize(stringReader, _options); return result; } } }
这里做了两个关键改进:
- 使用
async/await异步读取流到末尾,确保获取完整的JSON内容 - 将读取到的完整字符串用
StringReader传给Jil的反序列化方法,避免流读取的潜在问题
3. 检查Jil版本兼容性
如果你的Jil版本比较旧,可能存在某些数值类型反序列化的bug。建议升级到最新稳定版,通过NuGet更新:
Install-Package Jil -Version [最新版本号]
4. 验证TypedDeserializers的委托创建
你的TypedDeserializers类通过反射创建反序列化委托,逻辑本身没问题,但可以添加校验提前发现反射问题:
private static Func<TextReader, Options, object> CreateDelegate(Type type) { var genericMethod = _method.MakeGenericMethod(type); if(genericMethod == null) { throw new InvalidOperationException($"Failed to create generic deserialize method for type {type.FullName}"); } return (Func<TextReader, Options, object>)genericMethod.CreateDelegate(typeof(Func<TextReader, Options, object>)); }
这样可以提前排查反射过程中的异常,避免后续反序列化时的隐性错误
额外调试技巧
在ReadFromStreamAsync方法里添加日志,输出读取到的原始JSON内容,这样可以快速定位是否是请求数据的问题:
var json = await reader.ReadToEndAsync(); // 添加日志输出json内容,比如用内置Trace或日志框架 System.Diagnostics.Trace.WriteLine($"Received JSON: {json}");
内容的提问来源于stack exchange,提问作者Satheeshkumar
相关产品推荐
相关产品推荐

