Pan*_*rma 2 c# serialization json dynamic deserialization
我也遇到了一个问题。我能够将嵌套的 JSON 转换为 key-Value ,但现在我想将其转换回其原始的 json 格式。对于我的问题,我无法使用 C# 对象模型来执行此操作,因为我拥有的 JSON 文件是动态的,并且其结构会随着时间的推移而发生变化。所以我正在寻找我们可以通过更新的键值对序列化和反序列化 JSON 的解决方案。任何帮助将是极大的解脱。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
Run Code Online (Sandbox Code Playgroud)
}
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);
Run Code Online (Sandbox Code Playgroud)
这段代码的输出是这样的:
[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, ]
Run Code Online (Sandbox Code Playgroud)
我想将它转换回原来的 JSON 结构。
以下内容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);
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
在这里,我编写了一个自定义函数来查找键并替换它的值,
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;
}
Run Code Online (Sandbox Code Playgroud)
重要提示:这里的第四个参数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();
Run Code Online (Sandbox Code Playgroud)
输出:
参考: Brian Rogers, senshin
| 归档时间: |
|
| 查看次数: |
3590 次 |
| 最近记录: |