json.net:序列化从ObservableCollection派生的类型的问题

时间:2014-09-10 09:42:27

标签: c# serialization json.net

我有一个扩展基本ObservableCollection<T>类的类(添加了更多属性)。当我使用json.net序列化类时,它省略了添加的属性。例如,以下类:

public class ObservableCollectionExt : ObservableCollection<int>
{
    [DataMember]
    public string MyData1 { get; set; }

    [DataMember]
    public string MyData2 { get; set; }

    public ObservableCollectionExt()
    {
    }

    [JsonConstructor]
    public ObservableCollectionExt(string mydata1, string mydata2)
    {
        MyData1 = mydata1;
        MyData2 = mydata2;
    }

    public static ObservableCollectionExt Create()
    {
        ObservableCollectionExt coll = new ObservableCollectionExt("MyData1", "MyData2");

        coll.Add(1);
        coll.Add(2);
        coll.Add(3);

        return coll;
    }

}

按如下方式序列化(缺少MyData1MyData2的值):

{   “$ type”:“Test1.ObservableCollectionExt,Test1”,   “$ values”:[     1,     2,     3   ] }

如何在序列化数据中包含额外属性?

1 个答案:

答案 0 :(得分:1)

您可能需要自定义转换器。不确定这是最好的方法,但似乎有效。

        public class MyCustomConverter : JsonConverter
        {
            public override bool CanConvert(Type objectType)
            {
                return objectType == typeof(ObservableCollectionExt);
            }

            public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
            {
                ObservableCollectionExt result = new ObservableCollectionExt();
                string type = null;
                int i;
                while (reader.Read())
                {
                    if (reader.TokenType == JsonToken.PropertyName)
                        type = reader.Value.ToString();
                    else if (reader.TokenType == JsonToken.EndObject)
                        return result;
                    else if (!string.IsNullOrEmpty(type) && reader.Value != null)
                    {
                        switch (type)
                        {
                            case "mydata1":
                                {
                                    result.MyData1 = reader.Value.ToString();
                                    break;
                                }
                            case "mydata2":
                                {
                                    result.MyData2 = reader.Value.ToString();
                                    break;
                                }
                            case "elements":
                                {
                                    if (int.TryParse(reader.Value.ToString(), out i))
                                        result.Add(i);
                                    break;
                                }
                        }
                    }
                }
                return result;
            }

            public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
            {
                ObservableCollectionExt o = (ObservableCollectionExt)value;

                writer.WriteStartObject();

                writer.WritePropertyName("mydata1");
                writer.WriteValue(o.MyData1);

                writer.WritePropertyName("mydata2");
                writer.WriteValue(o.MyData2);

                writer.WritePropertyName("elements");
                writer.WriteStartArray();
                foreach (var val in o)
                    writer.WriteValue(val);
                writer.WriteEndArray();

                writer.WriteEndObject();
            }
        }

这会生成如下字符串:{\"mydata1\":\"MyData1\",\"mydata2\":\"MyData2\",\"elements\":[1,2,3]}

像这样使用转换器:

        ObservableCollectionExt o = ObservableCollectionExt.Create();
        JsonSerializerSettings settings = new JsonSerializerSettings();
        settings.Converters.Add(new MyCustomConverter());
        string serialized = JsonConvert.SerializeObject(o, settings);
        ObservableCollectionExt deserialized = JsonConvert.DeserializeObject<ObservableCollectionExt>(serialized, settings);

修改

我意识到转换器只适用于自定义属性不是复杂类型的简单情况。还有另一种方法,一种使用匿名类型的解决方法:

    ObservableCollectionExt o = ObservableCollectionExt.Create();
    string serialized = JsonConvert.SerializeObject(new { MyData1 = o.MyData1, MyData2 = o.MyData2, coll = o });
    var anonType = new { MyData1 = null as object, MyData2 = null as object, coll = null as object };
    dynamic d = JsonConvert.DeserializeAnonymousType(serialized, anonType);
    ObservableCollectionExt deserialized = new ObservableCollectionExt(d.MyData1, d.MyData2);
    foreach (var elem in d.coll)
        deserialized.Add((int)elem);