本地正常UAT异常:NewtonSoft JsonConvert.DeserializeObject报错
解决Newtonsoft.Json反序列化时的System.Reflection.DefaultMemberAttribute异常
问题背景
你遇到的情况确实有点棘手:本地Win10 IIS部署时代码运行完全正常,但到UAT服务器上就出问题了,反序列化JSON的时候抛出了和System.Reflection.DefaultMemberAttribute相关的异常。先把你提供的关键信息理清楚:
要反序列化的JSON内容:
{ "header": { "application-code": "ZZZ" }, "piece": [ "0000001" ] }
对应的实体类定义:
public class RequestPiece { [JsonProperty(PropertyName = "header")] public RequestHeaderPiece requestheader { get; set; } } public class ResponseHeaderPiece { [JsonProperty(PropertyName = "application-code")] public string application_code { get; set; } } public class ResponsePiece { [JsonProperty(PropertyName = "header")] public ResponseHeaderPiece responseheader { get; set; } [JsonProperty(PropertyName = "piece")] public List<string> piece { get; set; } }
触发异常的核心代码段:
public List<string> getP(string pieces) { try{ restAPI.Url = config.PieceServiceUrl + "/" + pieces; restAPI.Method = "GET"; restAPI.ClientId = config.ClientId; restAPI.Secret = config.SecretKey; string returnString = restAPI.callJsonService(); log.Info(System.Reflection.MethodInfo.GetCurrentMethod() + "::JSON response => " + returnString); ResponsePiece rp = JsonConvert.DeserializeObject<ResponsePiece>(returnString); log.Info(System.Reflection.MethodInfo.GetCurrentMethod() + "::JSON response " + rp.piece); return rp.piece; } catch (Exception ex) { log.Error(System.Reflection.MethodInfo.GetCurrentMethod() + "::failed::" + ex.Message.ToString() + " => " + ex.StackTrace.ToString()); return null; } }
异常堆栈的关键报错信息:
System.Reflection.DefaultMemberAttribute.m_memberName => at System.Reflection.RtFieldInfo.PerformVisibilityCheckOnField(IntPtr field, Object target, IntPtr declaringType, FieldAttributes attr, UInt32 invocationFlags) at System.Reflection.RtFieldInfo.InternalGetValue(Object obj, Boolean doVisibilityCheck, Boolean doCheckConsistency) at System.Reflection.RtFieldInfo.GetValue(Object obj) at System.Attribute.GetHashCode() ... at Newtonsoft.Json.Serialization.DefaultContractResolver.InitializeContract(JsonContract contract)
问题根源分析
这个异常本质是反射访问权限的差异问题:本地Win10的IIS通常运行在权限较高的上下文(比如你的个人用户账户),而UAT服务器的应用池一般用更受限的身份(比如ApplicationPoolIdentity)。旧版本的Newtonsoft.Json在解析契约时,会直接反射访问DefaultMemberAttribute的私有字段m_memberName,在权限受限的环境下这种操作会被拦截,进而抛出异常。
解决方案(按优先级推荐)
1. 升级Newtonsoft.Json到最新稳定版
这是最彻底的解决方式——这个问题是Json.NET旧版本的已知bug,新版本已经修复了这个反射权限问题,改用了更安全的方式获取属性信息,不再直接访问私有字段。
- 打开项目的NuGet包管理器,找到
Newtonsoft.Json,升级到最新的稳定版本(比如13.x及以上) - 重新编译部署到UAT服务器测试
2. 临时调整应用池权限(不推荐,仅应急使用)
如果因为项目限制无法升级Json.NET,可以临时调整UAT服务器的应用池权限:
- 打开IIS管理器,找到你的应用对应的应用池
- 右键选择「高级设置」,将「标识」从
ApplicationPoolIdentity改为LocalSystem或其他具有更高权限的账户 - 注意:这种方式会降低服务器的安全性,只适合紧急排查时临时使用
3. 自定义契约解析器(备选方案)
如果升级后仍有问题,可以自定义一个契约解析器,跳过可能引发异常的反射检查:
public class SafeContractResolver : DefaultContractResolver { protected override JsonContract CreateContract(Type objectType) { try { return base.CreateContract(objectType); } catch (ReflectionTypeLoadException) { // 忽略反射加载异常,返回默认基元契约 return base.CreatePrimitiveContract(objectType); } catch (Exception) { // 捕获其他反射相关异常,降级处理 return base.CreateContract(objectType); } } }
然后在反序列化时指定使用这个解析器:
var jsonSettings = new JsonSerializerSettings { ContractResolver = new SafeContractResolver() }; ResponsePiece rp = JsonConvert.DeserializeObject<ResponsePiece>(returnString, jsonSettings);
验证步骤
- 优先尝试升级Json.NET,这是最稳妥的解决路径
- 升级后重新部署到UAT,测试接口是否正常工作
- 若升级不可行,再尝试调整应用池权限或自定义解析器
内容的提问来源于stack exchange,提问作者user9671207
相关产品推荐
相关产品推荐

