【问题标题】:Deserializing inner structure to string with JavaScriptSerializer in .NET在 .NET 中使用 JavaScriptSerializer 将内部结构反序列化为字符串
【发布时间】:2015-09-04 09:08:51
【问题描述】:

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

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

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

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

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

但是,我的应用程序的“上层”将知道如何处理这些数据。

因此,我需要想办法将 Value 字段保留为字符串,无论它包含整数、字符串还是完整的 JSON 结构。基本上,我不希望JavaScriptSerializer 解析其中的任何内容。我很想能有这样的课程:

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

Value 包含我的 JSON 中未处理的原始值。

有没有办法告诉 .NET 不要解析我的 JSON 的某些部分?

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

【问题讨论】:

  • 我必须说 JSON.Net 是最好的json 解析库。
  • 我知道并且我在许多其他项目中多次使用它:) 但是它对我的项目来说完全是矫枉过正,我真的必须使用标准 .NET 运行时提供的东西,仅此而已!跨度>
  • ASP.NET MVC also 使用 Json.Net,这应该可以解决需求。 “作为库”的要求并不意味着您不能使用 Json.NET。它并不过分,它比过时的 JavaScriptSerializer 更简单、更容易、更兼容。
  • 此外,什么是问题所在?您不能简单地反序列化为您提供的类型吗?您尝试了哪些方法,问题是什么?
  • @PanagiotisKanavos “我遇到的问题是,在 "Type": "JsonData" 的情况下,对象可以是任意的。我无法对其结构做出任何假设。 "

标签: c# .net json javascriptserializer


【解决方案1】:

没有一个属性可以指示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

【讨论】:

  • 感谢您的解决方案!在此期间,我决定按照您的建议重新序列化。虽然没有转换器。不过,您的解决方案有点清洁!
【解决方案2】:

试试这个:

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

【讨论】:

  • 谢谢,我已经尝试过了,是的,它可以正确反序列化。然而,我遇到的问题是我真的需要Value 是一个字符串而不是object。这就是我的代码的上半部分所期望的!
  • 你的要求有点奇怪。加上with "Value": 3.14Value 不是string
  • 我知道这不是字符串。我的意思是,上层会知道如何处理"3.14""\"Hello\""
  • 那么,他们可能也知道object
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多