Глубоко найти или найти ключ на любом уровне в JSON и заменить его значение в c # - PullRequest
0 голосов
/ 14 января 2019

Я также поражен своего рода проблемой. Я могу преобразовать вложенный 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

}

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.

1 Ответ

0 голосов
/ 14 января 2019

Ниже ExtensionMethods может помочь вам обновить любое значение ключа в вашем 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;
}

Важно: Что за четвертый параметр occurence означает здесь?

  • Если вы введете 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();

Выход:

enter image description here

Ссылка: Брайан Роджерс , senshin

...