JSON反序列化中的类型提示
本文关键字:类型 提示 反序列化 JSON | 更新日期: 2023-09-27 18:23:58
我一直在使用ASP.NET
(asmx)WebService
通过AJAX
与服务器通信。我现在正在WebMethods
中使用复杂类型。我的问题是,我的一个类有一个类型为接口的属性。
当串行化时,一切都很好,因为实例类型是已知的。取消序列化后,JSON
转换器不知道要转换为的类型,因为它无法创建我的接口的实例。所以我看了一下类型提示,特别是多态性部分,我一直在努力让它发挥作用,但没有成功。
这是我的代码示例:
[WebService(Namespace = "http://tempuri.org/")]
[ScriptService]
public class MyService : System.Web.Services.WebService {
public MyService () { }
[WebMethod(EnableSession = true)]
[ScriptMethod]
public void SaveThing(Thing myThing)
{
//Do stuff
}
}
public interface IItem : ISerializable
{
int Id { get; }
string Options { get; }
}
[DataContract(Namespace="MyNamespace", Name="Item")]
public class Item : IItem
{
[DataMember]
public string Url
{
get { return m_url; }
}
}
[Serializable]
public class Thing
{
public int Id { get; set; }
public IItem MyItem { get; set; }
}
在序列化时,我得到了myThing (Thing)
的__type
属性,但没有得到属性MyItem (Item)
的属性。我试着通过操纵JSON
并将其发送回来强制它,但我只得到了InvalidServiceOperation
。我是不是在尝试一些不被允许的事情?MSDN文档似乎没有提到我不能使用类型提示来实例化接口,但它的示例确实暗示了类和派生类。
如果可能的话,我想继续使用属性进行序列化,而不是自定义代码,因为我认为它更整洁。尽管如此,仍对编码解决方案持开放态度。
好吧,经过更多的搜索和研究,我找到了一个解决方案,它没有我想要的那么整洁和漂亮,但它很有效。
首先,什么不起作用。所以我尝试使用ISerializable
,用GetObjectData()
和一个去序列化构造函数实现了我的类
[Serializable]
public class Thing : ISerializable
{
public int Id { get; set; }
public IItem MyItem { get; set; }
public Thing(SerializationInfo info, StreamingContext context){
{
//Do deserialization and handle IItem object
}
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
//Do serialization
}
}
现在我认为这不起作用,因为Thing
的所有属性都在调用此构造函数之前被取消序列化,导致本机序列化程序试图取消我的接口的序列化。
关于什么起了作用。自定义JavascriptConverter
进行救援。因此,我更改了Web服务,将字符串作为参数,而不是复杂对象(我不太喜欢这个位),然后实现了一个已知类型为IItem
的JavascriptConverter
,以将取消序列化处理为一个具体的类。
public class ItemConverter : JavaScriptConverter
{
public override IEnumerable<Type> SupportedTypes
{
get { return new List<Type>() { typeof(IItem) }; }
}
public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
{
throw new NotImplementedException();
}
public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
{
//If we are of type IItem
if (dictionary.ContainsKey("Type")) //My check to make sure we are of type IItem
{
var factory = new ItemFactory();
return factory.CreateItem((int)dictionary["Id"], (string)dictionary["Options"], (ItemTypes)dictionary["Type"]);
}
else
{
return null;
}
}
}
[WebService(Namespace = "http://tempuri.org/")]
[ScriptService]
public class MyService : System.Web.Services.WebService {
public MyService () { }
[WebMethod(EnableSession = true)]
[ScriptMethod]
public void SaveThing(string myThing)
{
//Get our custom converter
var itemConverter = new ItemConverter();
var serialiser = new JavaScriptSerializer();
//Register it
serialiser.RegisterConverters(new List<JavaScriptConverter>() { itemConverter });
//Deserialise the dashboard
var theThing = serialiser.Deserialize<Thing>(myThing);
//Save
theThing.Save();
}
}
我希望这能帮助到一些人,如果有人有更优雅的解决方案,我很乐意看到他们。此外,在整个过程中,我不想对第三方库(如Json.NET
或NewtonSoft JSON
等)有任何依赖。