您可以创建一个辅助方法来执行此操作。辅助方法可以首先将所有内容反序列化为 JToken 层次结构,然后使用您提供的替换函数递归搜索和替换变量。替换后,它可以使用JToken.ToObject() 将其水合到您的目标类中。该计划中唯一的问题是原始 JSON 必须是有效的。因此,我建议为您的变量使用特殊格式的字符串值,这样就不会与正常的字符串值混淆。也许是这样的:
{
"foo": "$(bar)"
}
帮助程序的代码如下所示:
public static class JsonHelper
{
public static T DeserializeAndReplace<T>(string json, Func<string, object> replaceFunc)
{
return ReplaceVariables(JToken.Parse(json), replaceFunc).ToObject<T>();
}
public static JToken ReplaceVariables(JToken token, Func<string, object> replaceFunc)
{
if (token.Type == JTokenType.Object)
{
JObject copy = new JObject();
foreach (JProperty prop in token.Children<JProperty>())
{
copy.Add(prop.Name, ReplaceVariables(prop.Value, replaceFunc));
}
return copy;
}
if (token.Type == JTokenType.Array)
{
JArray copy = new JArray();
foreach (JToken item in token.Children())
{
copy.Add(ReplaceVariables(item, replaceFunc));
}
return copy;
}
if (token.Type == JTokenType.String)
{
string s = (string)token;
if (s.StartsWith("$(") && s.EndsWith(")"))
{
object value = replaceFunc(s.Substring(2, s.Length - 3));
return (value != null ? JToken.FromObject(value) : JValue.CreateNull());
}
}
return token;
}
}
这是一个演示帮助器的演示:
class Program
{
static void Main(string[] args)
{
string json = @"
[
{
""name"" : ""normal"",
""bar"" : { ""baz"" : ""quux"" }
},
{
""name"" : ""$(cool)"",
""bar"" : ""$(bar)""
},
]";
var list = JsonHelper.DeserializeAndReplace<List<Foo>>(json, ReplaceVariable);
foreach (Foo foo in list)
{
Console.WriteLine("name: " + foo.Name);
Console.WriteLine("bar.baz: " + foo.Bar.Baz);
Console.WriteLine();
}
}
private static object ReplaceVariable(string variable)
{
if (variable == "bar") return new Bar { Baz = "foobar" };
if (variable == "cool") return "whip";
return null;
}
}
class Foo
{
public string Name { get; set; }
public Bar Bar { get; set; }
}
class Bar
{
public string Baz { get; set; }
}
输出:
name: normal
bar.baz: quux
name: whip
bar.baz: foobar
小提琴:https://dotnetfiddle.net/5T9lmd