派生对象列表的序列化
serialization of List of derived objects
我想将派生对象列表序列化为 json 并反序列化。序列化工作正常,反序列化无法将对象转换为派生 class 对象,所有对象都被反序列化为基础 class 对象并丢失属于派生 class 的成员。
我有基础 class AutoEvent,并派生了 classes MouseClickEvent 和 ClickImageEvent,所以一次
我反序列化以列出所有对象都是 AutoEvent 类型。我如何反序列化以便将每个对象转换为派生的 class 对象?
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Reflection;
using System.Web.Script.Serialization;
namespace AutoEvent
{
public class AutoEvent
{
public string Name { get; set; }
public int DelayMs { get; set; }
public AutoEvent(string name, int delayMs)
{
Name = name;
DelayMs = delayMs;
}
public AutoEvent() { }
}
public class MouseClickEvent : AutoEvent
{
public Rectangle RectArea { get; set; }
public bool IsDoubleClick { get; set; }
public MouseClickEvent(string name, int delayMs, Rectangle rectArea, bool isDoubleClick) : base(name, delayMs)
{
RectArea = rectArea;
IsDoubleClick = isDoubleClick;
}
public MouseClickEvent() { }
}
public class ClickImageEvent : AutoEvent
{
public List<string> ImgFiles { get; set; }
public Rectangle SearchArea { get; set; }
public double ImgTolerance { get; set; }
public double ImgError { get; set; }
public bool IsDoubleClick { get; set; }
public ClickImageEvent(string name, int delayMs, Rectangle searchArea, bool isDoubleClick, double imgTol, double imgErr) : base(name, delayMs)
{
SearchArea = searchArea;
IsDoubleClick = isDoubleClick;
ImgTolerance = imgTol;
ImgError = imgErr;
}
public ClickImageEvent() { }
}
class Program
{
static void Main(string[] args)
{
string path = @"c:/nenad/testSer.txt";
List<AutoEvent> events = new List<AutoEvent>();
MouseClickEvent clickEvent1 = new MouseClickEvent("mouse click1", 100, new Rectangle(20, 30, 15, 10), true);
MouseClickEvent clickEvent2 = new MouseClickEvent("mouse click2", 15, new Rectangle(20, 45, 15, 10), true);
ClickImageEvent imgclick1 = new ClickImageEvent("image click1", 15, new Rectangle(20, 45, 555, 150), false, 0.1, 0.05);
ClickImageEvent imgclick2 = new ClickImageEvent("image click2", 125, new Rectangle(2220, 45, 5525, 150), false, 0.15, 0.25);
events.Add(clickEvent1);
events.Add(clickEvent2);
events.Add(imgclick1);
events.Add(imgclick2);
JavaScriptSerializer ser = new JavaScriptSerializer();
string json = ser.Serialize(events);
if (!File.Exists(path))
{
using (var h = File.Create(path)) ;
}
File.WriteAllText(path, json);
json = File.ReadAllText(path);
events = ser.Deserialize<List<AutoEvent>>(json);
MouseClickEvent event1 = (MouseClickEvent)events[0]; // fails at runtime to convert
ClickImageEvent event2 = (ClickImageEvent)events[2]; // fails at runtime to convert
}
}
}
来自关于 javascriptserializer
的文档
For .NET Framework 4.7.2 and later versions, use the APIs in the System.Text.Json namespace for serialization and deserialization. For earlier versions of .NET Framework, use Newtonsoft.Json. This type was intended to provide serialization and deserialization functionality for AJAX-enabled applications
即您可能应该使用另一个 json 库。
如果您更喜欢 Json.Net,请参阅 Json.net serialize/deserialize derived types?. If you prefer System.Text.Json, see How to serialize properties of derived classes with System.Text.Json
当你运行
events = ser.Deserialize<List<AutoEvent>>(json);
你只能得到这个
[
{
"Name": "mouse click1",
"DelayMs": 100
},
{
"Name": "mouse click2",
"DelayMs": 15
},
{
"Name": "image click1",
"DelayMs": 15
},
{
"Name": "image click2",
"DelayMs": 125
}
]
json 中的内容无关紧要,它将自动剪切为 AutoEvent class 中的数据,因为您正在使用它进行反序列化。
为了得到所有的信息,你必须使用最高的继承级别来反序列化,而不是最低的。此代码在 VS 中测试并正常工作。
List<ClickImageEvent> events1 = ser.Deserialize<List<ClickImageEvent>>(json);
MouseClickEvent event1 = (MouseClickEvent)events[0];
ClickImageEvent event2 = (ClickImageEvent)events[2];
并且所有 classes 应该相互继承
public class ClickImageEvent : MouseClickEvent
{
public List<string> ImgFiles { get; set; }
public Rectangle SearchArea { get; set; }
public double ImgTolerance { get; set; }
public double ImgError { get; set; }
public ClickImageEvent(string name, int delayMs, Rectangle searchArea, bool isDoubleClick, double imgTol=0, double imgErr=0) : base(name, delayMs,searchArea, isDoubleClick)
{
SearchArea = searchArea;
IsDoubleClick = isDoubleClick;
ImgTolerance = imgTol;
ImgError = imgErr;
}
public ClickImageEvent() { }
}
或者如果您只想从 AutoEvent 派生,您可以使用映射器或手动转换或使用 linq Select
var ev =events[0];
MouseClickEvent event1 = new MouseClickEvent( ev.Name, ev.DelayMs, ev.SeachArea,...);
如果您需要使用 linq 进行转换,则必须添加 class
类型
public class AutoEvent
{
public string TypeName { get; set; } = "Auto";
.....
}
在序列化之前创建对象时应该分配。
我想将派生对象列表序列化为 json 并反序列化。序列化工作正常,反序列化无法将对象转换为派生 class 对象,所有对象都被反序列化为基础 class 对象并丢失属于派生 class 的成员。 我有基础 class AutoEvent,并派生了 classes MouseClickEvent 和 ClickImageEvent,所以一次 我反序列化以列出所有对象都是 AutoEvent 类型。我如何反序列化以便将每个对象转换为派生的 class 对象?
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Reflection;
using System.Web.Script.Serialization;
namespace AutoEvent
{
public class AutoEvent
{
public string Name { get; set; }
public int DelayMs { get; set; }
public AutoEvent(string name, int delayMs)
{
Name = name;
DelayMs = delayMs;
}
public AutoEvent() { }
}
public class MouseClickEvent : AutoEvent
{
public Rectangle RectArea { get; set; }
public bool IsDoubleClick { get; set; }
public MouseClickEvent(string name, int delayMs, Rectangle rectArea, bool isDoubleClick) : base(name, delayMs)
{
RectArea = rectArea;
IsDoubleClick = isDoubleClick;
}
public MouseClickEvent() { }
}
public class ClickImageEvent : AutoEvent
{
public List<string> ImgFiles { get; set; }
public Rectangle SearchArea { get; set; }
public double ImgTolerance { get; set; }
public double ImgError { get; set; }
public bool IsDoubleClick { get; set; }
public ClickImageEvent(string name, int delayMs, Rectangle searchArea, bool isDoubleClick, double imgTol, double imgErr) : base(name, delayMs)
{
SearchArea = searchArea;
IsDoubleClick = isDoubleClick;
ImgTolerance = imgTol;
ImgError = imgErr;
}
public ClickImageEvent() { }
}
class Program
{
static void Main(string[] args)
{
string path = @"c:/nenad/testSer.txt";
List<AutoEvent> events = new List<AutoEvent>();
MouseClickEvent clickEvent1 = new MouseClickEvent("mouse click1", 100, new Rectangle(20, 30, 15, 10), true);
MouseClickEvent clickEvent2 = new MouseClickEvent("mouse click2", 15, new Rectangle(20, 45, 15, 10), true);
ClickImageEvent imgclick1 = new ClickImageEvent("image click1", 15, new Rectangle(20, 45, 555, 150), false, 0.1, 0.05);
ClickImageEvent imgclick2 = new ClickImageEvent("image click2", 125, new Rectangle(2220, 45, 5525, 150), false, 0.15, 0.25);
events.Add(clickEvent1);
events.Add(clickEvent2);
events.Add(imgclick1);
events.Add(imgclick2);
JavaScriptSerializer ser = new JavaScriptSerializer();
string json = ser.Serialize(events);
if (!File.Exists(path))
{
using (var h = File.Create(path)) ;
}
File.WriteAllText(path, json);
json = File.ReadAllText(path);
events = ser.Deserialize<List<AutoEvent>>(json);
MouseClickEvent event1 = (MouseClickEvent)events[0]; // fails at runtime to convert
ClickImageEvent event2 = (ClickImageEvent)events[2]; // fails at runtime to convert
}
}
}
来自关于 javascriptserializer
的文档For .NET Framework 4.7.2 and later versions, use the APIs in the System.Text.Json namespace for serialization and deserialization. For earlier versions of .NET Framework, use Newtonsoft.Json. This type was intended to provide serialization and deserialization functionality for AJAX-enabled applications
即您可能应该使用另一个 json 库。
如果您更喜欢 Json.Net,请参阅 Json.net serialize/deserialize derived types?. If you prefer System.Text.Json, see How to serialize properties of derived classes with System.Text.Json
当你运行
events = ser.Deserialize<List<AutoEvent>>(json);
你只能得到这个
[
{
"Name": "mouse click1",
"DelayMs": 100
},
{
"Name": "mouse click2",
"DelayMs": 15
},
{
"Name": "image click1",
"DelayMs": 15
},
{
"Name": "image click2",
"DelayMs": 125
}
]
json 中的内容无关紧要,它将自动剪切为 AutoEvent class 中的数据,因为您正在使用它进行反序列化。
为了得到所有的信息,你必须使用最高的继承级别来反序列化,而不是最低的。此代码在 VS 中测试并正常工作。
List<ClickImageEvent> events1 = ser.Deserialize<List<ClickImageEvent>>(json);
MouseClickEvent event1 = (MouseClickEvent)events[0];
ClickImageEvent event2 = (ClickImageEvent)events[2];
并且所有 classes 应该相互继承
public class ClickImageEvent : MouseClickEvent
{
public List<string> ImgFiles { get; set; }
public Rectangle SearchArea { get; set; }
public double ImgTolerance { get; set; }
public double ImgError { get; set; }
public ClickImageEvent(string name, int delayMs, Rectangle searchArea, bool isDoubleClick, double imgTol=0, double imgErr=0) : base(name, delayMs,searchArea, isDoubleClick)
{
SearchArea = searchArea;
IsDoubleClick = isDoubleClick;
ImgTolerance = imgTol;
ImgError = imgErr;
}
public ClickImageEvent() { }
}
或者如果您只想从 AutoEvent 派生,您可以使用映射器或手动转换或使用 linq Select
var ev =events[0];
MouseClickEvent event1 = new MouseClickEvent( ev.Name, ev.DelayMs, ev.SeachArea,...);
如果您需要使用 linq 进行转换,则必须添加 class
类型public class AutoEvent
{
public string TypeName { get; set; } = "Auto";
.....
}
在序列化之前创建对象时应该分配。