如何在 C# 中遍历复杂的嵌套 Json 并在相同的 Json 中附加一些值集

How to traverse the complex nested Json in C# and append the some set of values in the same Json

我需要遍历下面的内容并在同一 JSON 模型中添加一组额外的值来形成最终输出。请帮助我如何添加,因为数据包含递归。

不应修改键的顺序。最终输出应该是相同的格式。 我想将此 JSON 反序列化为一些 类,更新更多数据,然后再将其序列化回 JSON。我们该怎么做?

从 Json 文件中读取: 输入:

      {
  "id" : "abv.123",
  "developName" : "ABV.123",
  "pay25" : {
    "0" : {
      "data" : "group35",
      "divison" : 0,
      "pay25" : {
        "0" : {
          "data" : "divisiondata",
          "divison" : 0,
          "divName" : "name33"        
        }
      }
    },
    "1" : {
      "data" : "group35",
      "divison" : 0,
      "pay25" : {
        "0" : {
          "data" : "group35",
          "divison" : 0,
          "pay25" : {
            "0" : {
              "data" : "label",
              "divison" : 0,
              "text" : "name55",
              "color1" : "green"
            }
          }
        },
        "1" : {
          "data" : "group35",
          "divison" : 0,
          "pay25" : {
            "0" : {
              "data" : "divisiondata",
              "divison" : 0,
              "divName" : "fab125"

            },
            "1" : {
              "data" : "divisiondata",
              "divison" : 0,
              "divName" : "gbt333"
            },
            "2" : {
              "data" : "divisiondata",
              "divison" : 0,
              "divName" : "test53"
            },
            "3" : {
              "data" : "divisiondata",
              "divison" : 0,
              "divName" : "test55"
            },
            "4" : {
              "data" : "divisiondata",
              "divison" : 0,
              "divName" : "teds422"
            },
            "5" : {
              "data" : "divisiondata",
              "divison" : 0,
              "divName" : "test66"
            },
            "6" : {
              "data" : "divisiondata",
              "divison" : 0,
              "divName" : "test982"
            },
            "7" : {
              "data" : "divisiondata",
              "divison" : 0,
              "divName" : "test322"
            },
            "8" : {
              "data" : "divisiondata",
              "divison" : 0,
              "divName" : "test633"
            },
            "9" : {
              "data" : "divisiondata",
              "divison" : 0,
              "divName" : "test622"
            },
            "10" : {
              "data" : "divisiondata",
              "divison" : 0,
              "divName" : "test733"
            },
            "11" : {
              "data" : "divisiondata",
              "divison" : 0,
              "divName" : "test71"
            }
          }
        }
      }
    },
    "2" : {
      "data" : "group35",
      "divison" : 0,
      "pay25" : {
        "0" : {
          "data" : "divisiondata",
          "divison" : 0,
          "divName" : "test9134234",
          "deps1" : [ {
            "datadiv123" : [ "1", "2" ],
            "value" : true
          } ]
        },
        "1" : {
          "data" : "divisiondata",
          "divison" : 0,
          "divName" : "test898932"
        },
        "2" : {
          "data" : "divisiondata",
          "divison" : 0,
          "divName" : "tewst432"
        }
      }
    },
    "3" : {
      "data" : "group35",
      "divison" : 0,
      "pay25" : {
        "0" : {
          "data" : "divisiondata",
          "divison" : 0,
          "divName" : "test352322",
           "deps1" : [ {
            "datadiv123" : [ "test", "tesstt" ],
            "value" : true
          } ]
        },
        "1" : {
          "data" : "divisiondata",
          "divison" : 0,
          "divName" : "test523432"
        },
        "2" : {
          "data" : "divisiondata",
          "divison" : 0,
          "divName" : "test634fdg"
        },
        "3" : {
          "data" : "divisiondata",
          "divison" : 0,
          "divName" : "tssg32432",
          "validators" : [ {
            "data" : "integer"
          } ]
        },
        "4" : {
          "data" : "divisiondata",
          "divison" : 0,
          "divName" : "test1111"
        },
        "5" : {
          "data" : "divisiondata",
          "divison" : 0,
          "divName" : "test2222"
        }
      }
    },
    "4" : {
      "data" : "group35",
      "divison" : 0,
      "pay25" : {
        "0" : {
          "data" : "divisiondata",
          "divison" : 0,
          "divName" : "test55632"
        }
      }
    },
    "5" : {
      "data" : "dynamicgrouptable",
      "operation" : [ "add", "delete" ],
      "dynamicValue" : {
        "0" : {
          "data" : "divisiondata",
          "divison" : 0,
          "divName" : "test953312"
        },
        "1" : {
         "data" : "divisiondata",
          "divison" : 0,
          "divName" : "test953312622"
        },
        "2" : {
          "data" : "divisiondata",
          "divison" : 0,
          "divName" : "test9533126499"
        },
        "3" : {
          "data" : "divisiondata",
          "divison" : 0,
          "divName" : "test953312644"
        }
      }
    }
  }
}

从此 JSON 中读取附加值集:

    {
    "name33": {
        "def1": "Value 1",
        "tip3": "Tip 53",
        "disp3": "develop 1",
        "path" : "Displayname"

    },
    "fab125": {
        "def1": "Value 5",
        "tip3": "strr11",
        "disp3": "develop 2",
        "path" : "Displayname"
    },
    "test322": {
        "def1": "Value 2",
        "tip3": "dev 53",
        "disp3": "develop 3",
        "path" : "Displayname"

    },
    {....},
{.....},
"test953312": {
        "def1": "Value 21",
        "tip3": "dev 5311",
        "disp3": "develop 334",
        "path" : "Displayname"

    },
    "test953312622": {
        "def1": "Value 212",
        "tip3": "dev 53222",
        "disp3": "develop 22113",
        "path" : "Displayname"

    },
    {....}

}

输出应该与两者合并 json 而不改变数据的顺序:

你可以使用 Newtonsoft.Json 它是 C# 中最常用的库。 因此,首先,您需要为您的数据创建一个模型。 我假设看起来像这样:

public class MyModel{
public List<MyModel> id {get;set;}
.....
}
public class MyTopLevelModel : MyModel{
public string reports{get;set;}
}

所以你可以这样做:

MyTopLevelModel myTopLevelModel = JsonConvert.DeserializeObject<MyTopLevelModel>(json);
//then get the place where you want to place the extra data like 
myTopLevelModel.id[0].id[0].value = "whatever"

之后就可以使用

var result = JsonConvert.SerializeObject(myTopLevelModel);

解决方案 1:

您可以使用 Newtonsoft.Json.LinqNewtonsoft.Json 来获取数据。由于您的数据不规则,反序列化它更复杂。它可能不会输出额外的字段。

   //deserialize
   JObject jObj = JObject.Parse(jsonString);
   JObject idObj = (JObject)jObj["id"];
   JObject idObj0 = (JObject)idObj["0"]["id"]["0"]; // 0 can replace to N, loop can deal with it.
   idObj0.add("value", "ewr");
   idObj0.add("type", "bool");
   //serialize
   string resultJsonString = jObj.ToString();

参考:Json.NET Modifying JSON

解决方案 2:

如果你更喜欢反序列化成class。您可以在 .Net 5 或 .Net Core 3.1

中使用本机库 System.Text.Json
      public class Model
      {
          public string reports {get; set;};
          public Dictionary<string, IdModel> id {get; set;};
      }

      public class IdModel
      {
           [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
           public string data {get; set;}
           [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
           public string text {get; set;}
           [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
           public string name {get; set;}
           [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
           public string display {get; set;}
           [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
           public string value {get; set;}
           [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
           public string type {get; set;}
           [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
           public Dictionary<string, IdModel> id {get; set;};
      }

      var data = JsonSerializer.Deserialize<Model>(jsonString);
      data.id["0"].id["0"].value = "ewr";
      data.id["0"].id["0"].type = "bool";
      .......
      string resultJsonString = JsonSerializer.Serialize<Model>(data);

参考:How to serialize and deserialize (marshal and unmarshal) JSON in .NET

我会选择方案一,因为数据比较复杂

这是您可以参考的代码

     using Newtonsoft.Json.Linq;

     var inputJObject = JObject.Parse(jsonString);
     var appendDataJObject = JObject.Parse(appendDataString);

     FindAndReplace(inputJObject, appendDataJObject);

     string resultString = inputJObject.ToString();

     public static void FindAndReplace(
          JObject input, 
          JObject appendData, 
          string keyName = "pay25", 
          string toReplaceFieldName = "divName")
     {
          foreach (var targetKey in ((JObject)input[keyName]))
          {
               var targetJObject = (JObject)targetKey.Value;

               //check whether there is pay25 property in child, if yes, search child recursively
               if (targetJObject.ContainsKey(keyName))
               {
                    FindAndReplace(targetJObject, appendData);
               }
               else
               {
                    //if no, check divName property existence
                    if (targetJObject.ContainsKey(toReplaceFieldName))
                    {
                         string divName = (string)targetJObject[toReplaceFieldName];
                         //check whether there is data has key = divName
                         if (appendData.ContainsKey(divName))
                         {
                              //append data
                              foreach (var data in (JObject)appendData[divName])
                              {
                                   targetJObject.Add(data.Key, data.Value);
                              }
                          }
                     }
                }
           }
      }

最后我觉得是一个如何递归替换数据的问题