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