添加JToken时遇Newtonsoft.Json.Linq.JProperty多值错误的技术求助
解决"Newtonsoft.Json.Linq.JProperty cannot have multiple values"错误
问题根源
你遇到的错误核心在于对JToken的层级理解有误:
additionalFields是**JArray类型**,它是父节点JProperty(键为additionalFields)的唯一值。- 你调用
additionalFields.AddAfterSelf(updatedToken)时,本质是在给这个JProperty添加第二个值,但JProperty的规则是只能拥有一个值,因此触发了报错。
简单来说:你不该给数组本身加兄弟节点,而是要修改数组内部的元素。
修复方案
方案1:定位目标元素后直接替换(推荐)
先找到要修改的元素,获取它在数组中的索引,移除旧元素后插入新元素(保持原位置):
// 查找目标字段 var targetField = additionalFields.FirstOrDefault(field => string.Equals(field["name"]?.ToString(), "newname", StringComparison.CurrentCultureIgnoreCase)); if (targetField != null) { int index = additionalFields.IndexOf(targetField); additionalFields.Remove(targetField); // 创建新token并插入到原位置 var updatedToken = CreateNewToken("newname", "newvalue"); additionalFields.Insert(index, updatedToken); }
方案2:遍历副本避免集合修改冲突
如果你需要保留遍历逻辑,记得先把数组转成副本(用ToList()),避免遍历原集合时修改导致的异常:
// 遍历数组的副本,防止修改原集合时的遍历异常 foreach (var additionalField in additionalFields.ToList()) { string currentName = additionalField["name"]?.ToString(); if (string.Equals(currentName, "newname", StringComparison.CurrentCultureIgnoreCase)) { int index = additionalFields.IndexOf(additionalField); additionalField.Remove(); var updatedToken = CreateNewToken("newname", "newvalue"); additionalFields.Insert(index, updatedToken); } }
额外优化:简化CreateNewToken方法
你的当前方法通过字符串拼接再解析的方式创建JToken,存在潜在的字符串转义问题(比如值包含引号时会出错)。可以直接用JObject构造,更安全高效:
public static JToken CreateNewToken(string name, string value) { return new JObject( new JProperty("name", name), new JProperty("value", value) ); }
为什么原代码会失败?
再明确一下层级关系:
{ "additionalFields": [ /* 这是JArray,是JProperty "additionalFields"的唯一值 */ ] }
当你调用additionalFields.AddAfterSelf(...),你是在JArray后面添加一个兄弟节点,也就是让JProperty "additionalFields"同时拥有JArray和你的新JToken两个值——这违反了JProperty的单值规则,所以报错。
内容的提问来源于stack exchange,提问作者DomBurf




