【问题标题】:Newtonsoft Rename extension method to rename a property name in JObject .net用于重命名 JObject .net 中的属性名称的 Newtonsoft 重命名扩展方法
【发布时间】:2021-05-11 04:59:33
【问题描述】:

我想替换 JObject 中的属性名称。我在网上搜索了一些解决方案。发现我们可以从 Newtonsoft 扩展重命名功能。
我也找到了扩展方法。重命名功能适用于问题中提到的 JObjects,但不适用于所有。
我的代码是这样的:

class Program
{
    static void Main(string[] args)
    {
        JObject o = JObject.Parse(@"{
              'Stores': [
                'Lambton Quay',
                'Willis Street'
              ],
              'Manufacturers': [
                {
                  'Name': 'Acme Co',
                  'Products': [
                    {
                      'Name': 'Anvil',
                      'Price': 50
                    }
                  ]
                },
                {
                  'Name': 'Contoso',
                  'Products': [
                    {
                      'Name': 'Elbow Grease',
                      'Price': 99.95
                    },
                    {
                      'Name': 'Headlight Fluid',
                      'Price': 4
                    }
                  ]
                }
              ]
            }");

        o.Property("Name").Rename("LongName");
        Console.WriteLine(o.ToString());
    }
}
public static class NewtonsoftExtensions
{
    public static void Rename(this JToken token, string newName)
    {
        if (token == null)
            throw new ArgumentNullException("token", "Cannot rename a null token");

        JProperty property;

        if (token.Type == JTokenType.Property)
        {
            if (token.Parent == null)
                throw new InvalidOperationException("Cannot rename a property with no parent");

            property = (JProperty)token;
        }
        else
        {
            if (token.Parent == null || token.Parent.Type != JTokenType.Property)
                throw new InvalidOperationException("This token's parent is not a JProperty; cannot rename");

            property = (JProperty)token.Parent;
        }

        // Note: to avoid triggering a clone of the existing property's value,
        // we need to save a reference to it and then null out property.Value
        // before adding the value to the new JProperty.  
        // Thanks to @dbc for the suggestion.

        var existingValue = property.Value;
        property.Value = null;
        var newProperty = new JProperty(newName, existingValue);
        property.Replace(newProperty);
    }
}

这给了我错误“无法重命名空指针”。
谁能告诉我我在这里做错了什么。非常感谢。

【问题讨论】:

    标签: c# json .net json.net


    【解决方案1】:

    使用此方法查找令牌。

    public static class JsonExtensions
    {
    public static List<JToken> FindTokens(this JToken containerToken, string name)
    {
        List<JToken> matches = new List<JToken>();
        FindTokens(containerToken, name, matches);
        return matches;
    }
    
    private static void FindTokens(JToken containerToken, string name, List<JToken> matches)
    {
        if (containerToken.Type == JTokenType.Object)
        {
            foreach (JProperty child in containerToken.Children<JProperty>())
            {
                if (child.Name == name)
                {
                    matches.Add(child.Value);
                }
                FindTokens(child.Value, name, matches);
            }
        }
        else if (containerToken.Type == JTokenType.Array)
        {
            foreach (JToken child in containerToken.Children())
            {
                FindTokens(child, name, matches);
            }
        }
    }
    

    }

    现在用这段代码来做剩下的事情:

    foreach (JToken token in o.FindTokens("Name"))
        {
            token.Rename("LongName");
        }
    

    实际上,在您的情况下,名称位于制造商数组中,但 o.Property("Name") 只会在根级别搜索它,结果为空。

    更新

    你说你想省略产品名称,你可以用一个小的 If 来做。用这个改变上面的代码。

    foreach (JToken token in o.FindTokens("Name"))
        {
           //Console.WriteLine(token.Path);
           if(!token.Path.Contains("Products"))
           token.Rename("LongName");
        }
    

    Fiddle for this Code

    【讨论】:

    • 非常感谢您的回复。它按预期工作。但是是否可以只重命名制造商的名称而不是产品名称?
    • 我添加了一个小如果来做你的伎俩。它会正常工作,但是如果有更多具有相同名称的嵌套属性,则需要正确解析属性路径。顺便说一句,很抱歉回复晚了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-09-08
    • 2021-05-20
    • 2020-04-19
    • 1970-01-01
    • 1970-01-01
    • 2018-01-11
    • 2018-08-06
    相关资源
    最近更新 更多