在 .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
我在 .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