0

I have a class that extends the basic ObservableCollection<T> class (adds some more properties). When I serialize the class using json.net, it omits the added properties. For example, the following class:

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

}

gets serialized as follows (with values for MyData1 and MyData2 missing):

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

How can I include the extra properties in the serialized data?

1 Answer 1

1

You may need a custom converter. Not sure that this is the best way to do it, but it seems to work.

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

This produces strings like this: {\"mydata1\":\"MyData1\",\"mydata2\":\"MyData2\",\"elements\":[1,2,3]}

Use the converter like this:

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

EDIT:

I realize the converter would only work for simple cases when the custom properties are not complex types. There is another way, a workaround with an anonymous type:

    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);
Sign up to request clarification or add additional context in comments.

1 Comment

using a converter works, but, since the extra properties, in my case, are actually other complex types, I would have to write serialization/deserialization code for all of them -- quite a daunting task! I am hoping there's a simpler solution.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.