JToken递归集合数据契约不支持报错,能否避免使用Newtonsoft处理?
报错根源分析
Type 'Newtonsoft.Json.Linq.JToken' is a recursive collection data contract which is not supported. Consider modifying the definition of collection 'Newtonsoft.Json.Linq.JToken' to remove references to itself.
- 该报错触发于
service.Create(history)执行阶段,并非JSON解析阶段:你直接将JToken派生类型的对象(item.No/item["No"]本质都是Newtonsoft的JValue类型,继承自JToken)赋值给了Entity的属性字段,当底层服务尝试序列化Entity对象提交时,会检测到JToken类型存在自引用的递归结构,WCF/Dataverse的序列化器不支持这类类型,因此抛出异常。 - 你修改后的代码仍然直接传递
item["No"]这个JToken对象给Entity属性,未做基础类型转换,所以还是触发相同报错。
无Newtonsoft的实现方案
根据你使用的.NET版本选择对应内置方案即可:
方案1:.NET Framework 环境(适配HttpWebRequest写法)
先引用程序集System.Web.Extensions,替换JSON解析逻辑:
string url = $"***"; tracingService.Trace(url); HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); request.Method = "GET"; NetworkCredential myNetworkCredential = new NetworkCredential("***@***.**", "***"); request.Credentials = myNetworkCredential; request.ContentType = "application/json"; HttpWebResponse response = (HttpWebResponse)request.GetResponse(); if (response.StatusDescription == "OK") { Stream dataStream = response.GetResponseStream(); StreamReader reader = new StreamReader(dataStream); string responseFromServer = reader.ReadToEnd(); tracingService.Trace(responseFromServer); // 用.NET内置序列化器,完全不需要Newtonsoft var serializer = new System.Web.Script.Serialization.JavaScriptSerializer(); dynamic result = serializer.Deserialize<dynamic>(responseFromServer); var items = result["value"]; foreach (var item in items) { // 每次循环创建新Entity,不要复用同一个实例 Entity history = new Entity("zst_casehistory"); // 转成基础字符串类型再赋值,禁止直接传解析器的包装类型 string no = item["No"].ToString(); tracingService.Trace(no); history["zst_servicereceiptno"] = no; service.Create(history); } }
方案2:.NET Core/.NET 5+ 环境
使用内置的System.Text.Json解析:
using System.Text.Json; // 前面请求逻辑不变,或者替换为更推荐的HttpClient写法 // ...省略Http请求部分代码... string responseFromServer = reader.ReadToEnd(); tracingService.Trace(responseFromServer); using JsonDocument doc = JsonDocument.Parse(responseFromServer); JsonElement root = doc.RootElement; JsonElement items = root.GetProperty("value"); foreach (JsonElement item in items.EnumerateArray()) { Entity history = new Entity("zst_casehistory"); // 显式转成基础类型再赋值 string no = item.GetProperty("No").GetString(); tracingService.Trace(no); history["zst_servicereceiptno"] = no; service.Create(history); }
额外注意事项
- 不要在循环外复用同一个Entity实例,每次创建新的实例,避免出现重复数据提交、主键冲突等问题。
- 所有从JSON中取出的值都要转换为string/int/DateTime等基础类型后再赋值给Entity属性,绝对不能直接传递JSON解析库的封装类型。
内容的提问来源于stack exchange,提问作者cryptoStp
相关产品推荐
相关产品推荐

