c# - 添加 JToken 时出现错误 Newtonsoft.Json.Linq.JProperty 不能有多个值

标签 c# json.net

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

{{"additionalFields": 
[
{ "name": "NAME1", "value": "VALUE1" },
{ "name": "NAME2", "value": "VALUE2" },
{ "name": "NAME3", "value": "VALUE3" },
{ "name": "NAME4", "value": "VALUE4" }
]}

我正在尝试更新其中一个 token 的值,例如将 VALUE1 更改为 VALUE10。

找到 token 后,我需要更新代码将其删除,如下所示。

additionalField.Remove();

然后,我使用以下函数创建一个新 token 来替换我已删除的 token (包含新值)。

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}\"}}";
}

然后,我按如下方式添加新 token 。

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!!
    }
}

但是添加 token 后我收到以下错误

Newtonsoft.Json.Linq.JProperty 不能有多个值

我可以在调试器中看到 token 已被删除(因为 token.Count 减少了 1),因此无法理解为什么我在添加替换 token 时遇到错误。

最佳答案

我能够在这里重现您的问题:https://dotnetfiddle.net/JIVCVB

出了什么问题

additionalFields 指的是包含namevalue JProperties 的JObject 的JArray。您正在循环访问此 JArray,尝试查找第一个具有特定值的 name 属性的 JObject,当您找到它时,您会尝试用全新的 JObject 替换该 JObject。您成功从 JArray 中删除了旧 JObject,但是当您执行 AddAfterSelf 插入新 JObject 时,您引用的是 additionalFields(复数)而不是 additionalField(单数)。回想一下,additionalFields 是 JArray。所以你是说你想在数组之后添加新的JObject。该数组的父级是一个名为 additionalFields 的 JProperty。 JProperty 只能有一个值,因此 AddAfterSelf 失败并出现您看到的错误。

如何修复代码

我认为您打算做的是additionalField.AddAfterSelf(updatedToken)。但是,由于不同的原因,这也会失败:此时您已经从 JArray 中删除了 additionalField,因此它不再具有父上下文。在删除要插入的项目之前,您需要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; 
}

fiddle :https://dotnetfiddle.net/KcFsZc

更简单的方法

您似乎要克服很多困难才能完成这项任务。您可以使用 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";
}

工作演示:https://dotnetfiddle.net/ZAKRmi

关于c# - 添加 JToken 时出现错误 Newtonsoft.Json.Linq.JProperty 不能有多个值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64915074/

相关文章:

c# - 如何使用 json.net 将数据表转换为 json 字符串?

c# - 为什么我的 Gnome 排序算法会导致我的系统挂起?

c# - 混淆删除数据上下文类

c# - LINQ to Entities 无法识别“System.String Format”方法

android - 运行 XamarinStore.Droid 时无法加载程序集 'Newtonsoft.Json'

c# - JSON 到 C# 对象(将复杂的 API 响应映射到 C# 对象)

c# - 将 BindList<Classname> 转换为 BindingList<Interface>

c# - 使用 CombinedGeometry 在 wpf 中连接两个多边形

vb.net - Newsoft JSON .NET 反序列化为 VB.net 中具有私有(private)属性的对象

c# - 将变量名设置为类型