这两天写了一个ILNumberics的包装类,涉及到序列化时,遇到一个ILArray<T>不能使用Json.net类库序列化的问题,折腾了半天,终于搞定了,把这个经验给大家分享一下:
1、序列化的类经常需要一个默认的不带参数的构造函数;
2、不能序列化的字段用Json.Net支持序列化回调方法,通过一个过渡的字段来代替它来序列化,通过序列化回调方法绑定这两个字段。举例如下:
1 [Serializable]
2 public abstract class Matrix<T>
3 {
4 #region 属性
5 protected int _rowCount, _columnCount;
6 [NonSerialized]
7 protected ILArray<T> _data;//此字段不能序列化
8 //protected T[] _dataArray;
9 [JsonProperty(Order = 2)]
10 public T[] DataArray//增加一个替代字段
11 {
12 get;
13 set;
14 }
15 [OnSerializing]//绑定Data与DataArray,序列化之前填充它。
16 internal void OnSerializing(StreamingContext context)
17 {
18 DataArray = new T[_rowCount*_columnCount];
19 for (int i = 0; i < _rowCount; i++)
20 {
21 for (int j = 0; j < _columnCount; j++)
22 {
23 DataArray[i*_columnCount + j] = _data.GetValue(i, j);
24 }
25 }
26 }
27 [OnSerialized]//绑定Data与DataArray,序列化后清空它,释放内存。
28 internal void OnSerialized(StreamingContext contex)
29 {
30 DataArray = null;
31 }
32 [OnDeserialized]//绑定Data与DataArray,反序列化后填充Data它。
33 internal void OnDeserialized(StreamingContext context)
34 {
35 _data = CreateILArray(DataArray, _rowCount, _columnCount);
36 }
37 [JsonProperty(Order = 0)]
38 public int RowCount { get { return _rowCount; } protected set { _rowCount = value; } }
39 [JsonProperty(Order = 1)]
40 public int ColumnCount { get { return _columnCount; } protected set { _columnCount = value; } }
41 [JsonIgnore]
42 public ILArray<T> Data { get { return _data; } }//此字段不能序列化
. ...
3、ILArray<T>不能序列化的字段通过自定义JsonConverter来实现:
1 public abstract class ILArrayJsonConvert<T> : JsonConverter
2 {
3
4 public override bool CanConvert(Type objectType)
5 {
6 return typeof(ILArray<T>).IsAssignableFrom((objectType));
7 }
8
9 public abstract ILArray<T> DeserializeData(JToken jtoken,int row,int col);
10
11 public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
12 {
13
14 var ret = serializer.Deserialize<JContainer>(reader);
15 if (ret.HasValues && ret.Count == 2)
16 {
17 var dim = (JArray) ret["Dimemsins"];
18 int row = (int)((double)dim[0]);
19 int col = (int)((double)dim[1]);
20 return DeserializeData(ret, row, col);
21 }
22 return null;
23 }
24 public abstract void SerializeData(JsonWriter write, IEnumerable<T> data,JsonSerializer serializer);
25 public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
26 {
27 ILArray<T> array = value as ILArray<T>;
28 var size = ILMath.size(array);
29 if (size.Values.Count() != 2)
30 {
31 throw new NotImplementedException("只实现了二维数组");
32 }
33 JsonSerializer js = new JsonSerializer();
34 writer.WriteStartObject();
35 writer.WritePropertyName("Dimemsins");
36 js.Serialize(writer, size.Values);
37 writer.WritePropertyName("Data");
38 SerializeData(writer, array.Values, serializer);
39 writer.WriteEndObject();
40
41 }
42 }
43 public class ILArrayDoubleJsonConvert : ILArrayJsonConvert<double>
44 {
45
46 public override ILArray<double> DeserializeData(JToken jtoken, int row, int col)
47 {
48 ILArray<double> arr = new ILArray<double>(row, col);
49 var data = (JArray)jtoken["Data"];
50 for (int i = 0; i < row; i++)
51 {
52 for (int j = 0; j < col; j++)
53 {
54 arr.SetValue((double)data[i + j * row], i, j);
55 }
56 }
57 return arr;
58 }
59 public override void SerializeData(JsonWriter write, IEnumerable<double> data, JsonSerializer serializer)
60 {
61 serializer.Serialize(write, data);
62 }
63 }
64
65 public class ILArrayComplexJsonConvert : ILArrayJsonConvert<complex>
66 {
67
68 public override ILArray<complex> DeserializeData(JToken jtoken, int row, int col)
69 {
70 ILArray<complex> arr = new ILArray<complex>(row, col);
71 var data = (JArray)jtoken["Data"];
72 for (int i = 0; i < row; i++)
73 {
74 for (int j = 0; j < col; j++)
75 {
76 arr.SetValue(new complex((double)data[2 * (i + j * row)], (double)data[2 * (i + j * row)+1]),
77 i, j);
78 }
79 }
80 return arr;
81 }
82 public override void SerializeData(JsonWriter write, IEnumerable<complex> data, JsonSerializer serializer)
83 {
84 write.WriteStartArray();
85 foreach (var item in data)
86 {
87 serializer.Serialize(write, item.real);
88 serializer.Serialize(write, item.imag);
89 }
90 }
91 }
92
93 [JsonObject(MemberSerialization = MemberSerialization.OptIn)]
94 public class MMatrix
95 {
96 protected ILArray<double> _data;
97 protected int _row,_col;
98 public int Row { get { return _row; } }
99 public int Col { get { return _col; } }
100 [JsonProperty]
101 [JsonConverter(typeof(ILArrayDoubleJsonConvert))]
102 public ILArray<double> Data { get { return _data; } set { _data = value; } }
103 public MMatrix(){}
104 public MMatrix(double[,] data) { Data = data; }
105
106 public static void test()
107 {
108 MMatrix m = new MMatrix(new double[,] { { 1, 2, 3 }, { 4, 5, 6 } });
109 var s = JsonConvert.SerializeObject(m);
110 var ret = JsonConvert.DeserializeObject<MMatrix>(s);
111 }
112 }