【问题标题】:JSON .NET Custom Symbol ResolverJSON .NET 自定义符号解析器
【发布时间】:2015-10-08 14:01:10
【问题描述】:

我想在反序列化一些 JSON 时使用变量。例如,如果我有 JSON 字符串(我知道这不是真正有效的 JSON):

{
   "foo": bar
}

我希望有机会解析符号bar

因此,在反序列化时,我希望得到与以下反序列化等效的结果:

{
  "foo": { "baz": "foobar" }
}

这可能使用 JSON .NET 吗?现在我得到了:

Additional information: Unexpected character encountered while parsing value: bar. Path 'foo', line 1, position 9.

【问题讨论】:

  • 不幸的是,如果它是“不是真正有效的 JSON”,那么您不太可能按照自己的意愿弯曲 JSON.NET。只是为了确定一下,可能值得深入研究源代码(这很容易理解)。

标签: .net json json.net deserialization


【解决方案1】:

您可以创建一个辅助方法来执行此操作。辅助方法可以首先将所有内容反序列化为 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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-04-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-21
    • 1970-01-01
    相关资源
    最近更新 更多