C# 在JSON中的任何级别深入查找或搜索键,并在c中替换其值#

C# 在JSON中的任何级别深入查找或搜索键,并在c中替换其值#,c#,json,serialization,dynamic,deserialization,C#,Json,Serialization,Dynamic,Deserialization,我还遇到了一个问题。我能够将嵌套的JSON转换为键值,但现在我想将其转换回原始JSON格式。至于我的问题,我不能使用C#对象模型来实现这一点,因为我拥有的JSON文件是动态的,它的结构会随着时间的推移而变化。因此,我正在寻找一种解决方案,通过它,我们可以通过更新的键值对序列化和反序列化JSON。任何帮助都会让你如释重负。蒂亚 示例JSON代码: { "firstName": "John", "lastName": "Smith", "isAlive": true, "age":

我还遇到了一个问题。我能够将嵌套的JSON转换为键值,但现在我想将其转换回原始JSON格式。至于我的问题,我不能使用C#对象模型来实现这一点,因为我拥有的JSON文件是动态的,它的结构会随着时间的推移而变化。因此,我正在寻找一种解决方案,通过它,我们可以通过更新的键值对序列化和反序列化JSON。任何帮助都会让你如释重负。蒂亚

示例JSON代码:

 {
  "firstName": "John",
  "lastName": "Smith",
  "isAlive": true,
  "age": 25,
  "address": {
  "streetAddress": "21 2nd Street",
  "city": "New York",
  "state": "NY",
  "postalCode": "10021-3100"
 },
"phoneNumbers": [
{
  "type": "home",
  "number": "212 555-1234"
 },
{
  "type": "office",
  "number": "646 555-4567"
},
{
  "type": "mobile",
  "number": "123 456-7890"
}
],
"children": [],
"spouse": null
}


我想把它转换回原来的JSON结构。

下面的
扩展方法可以帮助您在任何级别更新JSON中的任何键值

public static class JsonExtensions
{
    public static void SetByPath(this JToken obj, string path, JToken value)
    {
        JToken token = obj.SelectToken(path);
        token.Replace(value);
    }

    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);
            }
        }
    }
}
重要提示:这里的第四个参数
occurrence
是什么意思

  • 如果将
    null
    放入此参数中,则json中任何级别的所有指定键的值都将更新
  • 如果您放置任何索引,如
    0
    1
    ,则json中指定键的指定索引的值将在任何级别更新
你可以像这样使用它

string json = File.ReadAllText(@"Path to your json file");

JToken jToken = JToken.Parse(json);

jToken = FindAndReplace(jToken, "firstName", "Matthew", null);
jToken = FindAndReplace(jToken, "lastName", "Gilbert", null);
jToken = FindAndReplace(jToken, "streetAddress", "Falcon Ave, 91 Street, New Jersey", null);
jToken = FindAndReplace(jToken, "postalCode", "R12H34", null);

jToken = FindAndReplace(jToken, "type", "work", 0);
jToken = FindAndReplace(jToken, "number", "787-878-7878", 0);

jToken = FindAndReplace(jToken, "type", "factory", 1);
jToken = FindAndReplace(jToken, "number", "989-898-9898", 1);

string outputJson = jToken.ToString();
输出:

参考: ,

当前未在Json.NET中实现,请参见和,对于这一点,大家的共识是您必须使用自己的方法。我使用的Json不一致,可能会有所不同,因此键和数组不是静态的,它们可能会改变,所以我们如何才能做到这一点,因为我无法在我的cs文件中编写任何硬代码。我们将如何遍历像myClass这样的数组。DynamicData[“phoneNumbers”][0][“type”],因为json文件是在我的情况下动态创建的。对于您的第二条注释=>意味着您必须对数组中的每个索引项使用上述代码,对吗?这里的意思是
phoneNumbers
是数组,您必须在该数组上迭代。对于您的第一条注释=>您的服务器使用无模式json响应您的请求。因此,您如何知道如何处理特定密钥bcoz您不知道模式,然后您可能会被困在这里。我正在同步json文件中与其他配置文件(不在json中)匹配的几个值,因此我的目的是同步匹配的密钥并更新其值。
public static class JsonExtensions
{
    public static void SetByPath(this JToken obj, string path, JToken value)
    {
        JToken token = obj.SelectToken(path);
        token.Replace(value);
    }

    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);
            }
        }
    }
}
public static JToken FindAndReplace(JToken jToken, string key, JToken value, int? occurence)
{
    var searchedTokens = jToken.FindTokens(key);
    int count = searchedTokens.Count;

    if (count == 0)
        return $"The key you have to serach is not present in json, Key: {key}";

    foreach (JToken token in searchedTokens)
    {
        if (!occurence.HasValue)
            jToken.SetByPath(token.Path, value);
        else
        if (occurence.Value == searchedTokens.IndexOf(token))
            jToken.SetByPath(token.Path, value);
    }

    return jToken;
}
string json = File.ReadAllText(@"Path to your json file");

JToken jToken = JToken.Parse(json);

jToken = FindAndReplace(jToken, "firstName", "Matthew", null);
jToken = FindAndReplace(jToken, "lastName", "Gilbert", null);
jToken = FindAndReplace(jToken, "streetAddress", "Falcon Ave, 91 Street, New Jersey", null);
jToken = FindAndReplace(jToken, "postalCode", "R12H34", null);

jToken = FindAndReplace(jToken, "type", "work", 0);
jToken = FindAndReplace(jToken, "number", "787-878-7878", 0);

jToken = FindAndReplace(jToken, "type", "factory", 1);
jToken = FindAndReplace(jToken, "number", "989-898-9898", 1);

string outputJson = jToken.ToString();