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

本文关键字:类型 问题 派生 net 序列化 ObservableCollection json | 更新日期: 2023-09-27 18:21:24

我有一个扩展基本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.]}

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

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

您可能需要一个自定义转换器。不确定这是否是最好的方法,但它似乎奏效了。

        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);