在JSON中的任何级别深度查找或搜索密钥,并在c#中替换其值 [英] Deep find or search the key at any level in JSON and replace its value in c#

查看:241
本文介绍了在JSON中的任何级别深度查找或搜索密钥,并在c#中替换其值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我也遇到了某种问题.我能够将嵌套的JSON转换为键值,但是现在我想将其转换回其原始json格式.就我的问题而言,我无法使用C#对象模型来执行此操作,因为我拥有的JSON文件是动态的,并且其结构在一段时间内会发生变化.因此,我正在寻找一种解决方案,通过该解决方案,我们可以通过更新的键值对对JSON进行序列化和反序列化.任何帮助将是极大的缓解. TIA.

I am also struck in a sort of problem. I am able to convert the nested JSON into key-Value , but Now I want to convert it into back its orignal json format. As of my problem I can't use the C# Object Model to do this, because the JSON file that I have is dynamic and its structure changes over the period of time. So I am looking for the solution by which we can serialize and deserialize the JSON via updated Key-Value pair. Any help would be great relief. TIA.

示例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

}

var obj = JObject.Parse(json);

var result = obj.Descendants()
.OfType<JProperty>()
.Select(p => new KeyValuePair<string, object>(p.Path,
    p.Value.Type == JTokenType.Array || p.Value.Type == JTokenType.Object
        ? null : p.Value));

foreach (var kvp in result)
  Console.WriteLine(kvp);

此代码的输出如下:

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

我想将其转换回其原始JSON结构.

I want to convert it into back its original JSON structure.

推荐答案

下面的ExtensionMethods可以帮助您在任何级别上更新json中的任何键值.

The below ExtensionMethods can help you to update any key value in your json on any level.

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);
            }
        }
    }
}

在这里,我编写了一个自定义函数来查找密钥并替换其值,

And here I write one custom function that find the key and replace it's value,

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

重要:这里的第四个参数occurence是什么意思?

Important: What's the fourth parameter occurence mean here?

  • 如果在此参数中放入null,那么该值将针对任何级别的json中所有指定键的出现进行更新.
  • 如果您放置01之类的任何索引,则该值将在任何级别针对json中指定键的指定索引进行更新.
  • If you put null in this parameter then the value will be updated for all the occurrences of the specified key in json at any level.
  • If you put any index like 0, 1 then the value will be updated for the specified index of the specified key in json at any level.

您可以像

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();

输出:

参考: Brian Rogers senshin

这篇关于在JSON中的任何级别深度查找或搜索密钥,并在c#中替换其值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆