在 .NET 中使用 JavaScriptSerializer 将内部结构反序列化为字符串

Deserializing inner structure to string with JavaScriptSerializer in .NET

我在 .NET 中使用 JavaScriptSerializer 来反序列化结构,这些结构可以是您的标准扁平 key/value 对,如下所示:

{
    "Value": 3.14,
    "Type": "Real"
}

或更复杂,具有像这样的内部分层值对象:

{
    "Value": { "something": "test" },
    "Type": "JsonData"
}

我遇到的问题是,在"Type": "JsonData"的情况下,对象可以是任意的。我无法对它的结构做出任何假设。

但是,我的应用程序 "upper layers" 将知道如何处理这些数据。

因此我需要找到一种方法来将 Value 字段保持为字符串,无论它包含整数、字符串还是完整的 JSON结构体。基本上,我不希望 JavaScriptSerializer 解析其中的任何内容。我很希望能够拥有这样的 class:

public class JsonObject
{
    public string Value { get; set; }
    public string Type { get; set; }
}

Value 包含我的 JSON.

中未处理的原始值

有什么方法可以告诉 .NET 不要解析我的 JSON 的某些部分?

不要建议使用其他库,如JSON.NET。我知道它可能能够做到这一点,但这是针对将作为库分发的项目——这就是为什么我宁愿让我的库仅依赖于标准 .NET 框架。

试试这个:

public class JsonObject
{
    public object Value { get; set; }
    public object Type { get; set; }
}

没有指示 JavaScriptSerializer 不解析特定 JSON 属性 的属性(除了完全忽略它,这不是您想要的)。但是,您可以制作一个 JavaScriptConverter ,它可以有效地重新序列化有问题的 属性 ,这样您仍然可以获得您想要的结果:所有值都以字符串形式结束。

转换器可能如下所示:

public class JsonObjectConverter : JavaScriptConverter
{
    public override IEnumerable<Type> SupportedTypes
    {
        get { return new List<Type> { typeof(JsonObject) }; }
    }

    public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
    {
        JsonObject obj = new JsonObject();
        obj.Type = (string)dictionary["Type"];
        obj.Value = serializer.Serialize(dictionary["Value"]);
        return obj;
    }

    public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

要使用转换器,您必须使用 RegisterConverters 方法向 JavaScriptSerializer 注册它。这是一个演示:

class Program
{
    static void Main(string[] args)
    {
        string json = @"
        [
            {
                ""Value"" : ""foo bar"",
                ""Type"" : ""String""
            },
            {
                ""Value"" : 3.14,
                ""Type"" : ""Real""
            },
            {
                ""Value"" : 
                {
                    ""Something"" : ""Test"",
                    ""Items"" : [""A"", ""B"", ""C""]
                },
                ""Type"" : ""JsonData""
            },
            {
                ""Value"" : 42,
                ""Type"" : ""Integer""
            }
        ]";

        JavaScriptSerializer jss = new JavaScriptSerializer();
        jss.RegisterConverters(new List<JavaScriptConverter> { new JsonObjectConverter() });

        List<JsonObject> list = jss.Deserialize<List<JsonObject>>(json);
        foreach (JsonObject item in list)
        {
            Console.WriteLine(string.Format("({0}) {1}", item.Type, item.Value));
        }
    }
}

public class JsonObject
{
    public string Value { get; set; }
    public string Type { get; set; }
}

输出:

(String) "foo bar"
(Real) 3.14
(JsonData) {"Something":"Test","Items":["A","B","C"]}
(Integer) 42