C# 添加JToken时,获取错误Newtonsoft.Json.Linq.JProperty不能有多个值

C# 添加JToken时,获取错误Newtonsoft.Json.Linq.JProperty不能有多个值,c#,json.net,C#,Json.net,我有以下附加信息的结构,其中我需要更新结构中一个令牌的值。数据是一个jtoken数组,其父级名为“additionalFields”,如下所示: {{"additionalFields": [ { "name": "NAME1", "value": "VALUE1" }, { "name": "NAME2", "value": &quo

我有以下附加信息的结构,其中我需要更新结构中一个令牌的值。数据是一个jtoken数组,其父级名为“additionalFields”,如下所示:

{{"additionalFields": 
[
{ "name": "NAME1", "value": "VALUE1" },
{ "name": "NAME2", "value": "VALUE2" },
{ "name": "NAME3", "value": "VALUE3" },
{ "name": "NAME4", "value": "VALUE4" }
]}
我正在尝试更新其中一个令牌的值,例如将VALUE1更改为VALUE10

一旦我找到了令牌,我需要更新我的代码,并按如下方式删除它

additionalField.Remove();
additionalFields.AddAfterSelf(updatedToken);
然后,我使用以下函数创建一个新令牌来替换我已删除的令牌(包含新值)

public static JToken CreateNewToken(string name, string value)
{
    var stringToken = CreateNewStringToken(name, value);
    var token = JToken.Parse(stringToken);
     return (JToken) token;
}

private static string CreateNewStringToken(string name, string value)
{
    return $"{{\"name\":\"{name}\",\"value\":\"{value}\"}}";
}
然后我添加新的令牌,如下所示

additionalField.Remove();
additionalFields.AddAfterSelf(updatedToken);
综上所述,我们有以下几点

foreach (var additionalField in additionalFields)
{
    //is this the key we are looking for?
    var keyToken = additionalField.First;

    if (keyToken?.First == null) continue;
    if (string.Equals(keyToken.First.ToString(), "newname", StringComparison.CurrentCultureIgnoreCase))
    {
        //remove the current token
        additionalField.Remove();
        
        //add the updated token
        var updatedToken = CreateNewToken("newname", "newvalue");
        additionalFields.AddAfterSelf(updatedToken); <-- error occurs here!!
    }
}
foreach(附加字段中的var附加字段)
{
//这是我们要找的钥匙吗?
var-keyToken=additionalField.First;
如果(keyToken?.First==null)继续;
if(string.Equals(keyToken.First.ToString(),“newname”,StringComparison.CurrentCultureIgnoreCase))
{
//删除当前令牌
additionalField.Remove();
//添加更新的令牌
var updatedToken=CreateNewToken(“newname”、“newvalue”);

additionalFields.AddAfterSelf(updatedToken);我可以在这里重现您的问题:

出什么事了
additionalFields
引用包含
name
value
jproperty的JObject的JArray。您正在该JArray中循环,试图找到第一个具有
name
属性且具有特定值的JObject,当您找到它时,尝试用一个全新的JObject替换该JObject。您成功了吗成功地从JArray中删除旧JObject,但是当您执行插入新JObject的
AddAfterSelf
操作时,您引用的是
附加字段
(复数)而不是
附加字段
(单数)。回想一下,
additionalFields
是JArray。因此,您的意思是要在数组之后添加新的JObject。数组的父级是一个名为
additionalFields
的JPProperty。JPProperty只能有一个值,因此
AddAfterSelf
失败,出现错误

如何修复代码 我认为您打算做的是
additionalField.AddAfterSelf(updatetoken)
。但是,这也会失败,原因不同:此时您已经从JArray中删除了
附加字段
,因此它不再具有父上下文。在删除试图插入的项之前,您需要
AddAfterSelf
。如果您解决了这一问题,您还有另一个问题:您的循环在完成替换后不会发生异常,因此在循环集合时,您将收到一个关于修改集合的错误

以下是代码的相关部分及其更正:

if (string.Equals(keyToken.First.ToString(), "NAME1", StringComparison.CurrentCultureIgnoreCase))
{
    //add the updated token
    var updatedToken = CreateNewToken("newname", "newvalue");
    additionalField.AddAfterSelf(updatedToken);

    //remove the current token
    additionalField.Remove();
    
    // we found what we were looking for so no need to continue looping
    break; 
}
小提琴:

更简单的方法 要完成此任务,您似乎要经历很多困难。您可以使用
FirstOrDefault
来查找数组中要查找的对象,而不是循环。一旦找到了对象,就不需要替换整个对象;您可以直接更新属性值

以下是方法:

var rootObject = JToken.Parse(json);

// Get a reference to the array of objects as before
var additionalFields = rootObject["additionalFields"];

// Find the object we need to change in the array
var additionalField = additionalFields.FirstOrDefault(f => 
    string.Equals((string)f["name"], "NAME1", StringComparison.CurrentCultureIgnoreCase);

// if the object is found, update its properties
if (additionalField != null)
{
    additionalField["name"] = "newname";
    additionalField["value"] = "newvalue";
}

工作演示:

请展示所有相关代码。添加了额外的代码,希望能更好地了解问题哇,这是对我问题的精彩回答,您已经清楚地解释了我试图迭代JSON对象时的错误理解。非常感谢您花时间如此清楚地解释这一切,我真的很抱歉珍爱它。别担心,很高兴我能帮上忙!